tabs ↹ over ␣ ␣ ␣ spaces

by Jiří {x2} Činčura

Do attributes or fluent configurations take priority in Entity Framework Core?

29 Jan 2018 Entity Framework Core

I was teaching my Entity Framework Core course last two days and question about priority of attributes’ and configurations’ priority came. Let’s test it, shall we?

tl;dr;

Fluent configurations override attributes.

Full story

The fastest way to test this, is to define conflicting mapping and see how the query will look like.

I defined simple DbContext and even simpler entity. The entity has Table attribute mapping it to one table and in OnModelCreating I map it to different table using ToTable method. Just for fun I also tried the same with properties/columns using Column and HasColumnName respectively. It would be weird would the behavior differ.

class TestContext : DbContext
{
	protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
	{
		base.OnConfiguring(optionsBuilder);
		optionsBuilder.UseSqlServer(@"Data Source=(localdb)\mssqllocaldb;Initial Catalog=test;Integrated Security=True");
	}

	protected override void OnModelCreating(ModelBuilder modelBuilder)
	{
		base.OnModelCreating(modelBuilder);
		modelBuilder.Entity<TestEntity>()
			.ToTable("TableFromFluent")
			.Property(x => x.Name).HasColumnName("ColumnFromFluent");
	}
}

[Table("TableFromAttribute")]
class TestEntity
{
	public int Id { get; set; }
	[Column("ColumnFromAttribute")]
	public string Name { get; set; }
}

For testing I used the following code, without bothering about the database structure whatsoever. I’m interested in the query and I’m fine with the inevitable failure.

using (var db = new TestContext())
{
	db.GetService<ILoggerFactory>().AddConsole();
	db.Set<TestEntity>().Load();
}

The important part of log.

fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
      Failed executing DbCommand (6ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      SELECT [t].[Id], [t].[ColumnFromFluent]
      FROM [TableFromFluent] AS [t]

One can clearly see the table name as well as the column name are the ones from fluent configurations, not the ones used in attributes.

This makes perfect sense. You should be able to change in your configuration whatever was defined elsewhere where you might not be able or allowed to change it.