entity-framework-4 - TPH 继承映射使用 nchar (N'value') 而不是 char ('value' ) 作为鉴别器列值

标签 entity-framework-4 ef-code-first

我正在使用现有数据库并使用 EF 4.3 Code First。我有一个看起来像这样的实体层次结构,其中 Note 是基类:

Note
  - CompanyNote
  - OrderNote
  - etc

我正在使用 TPH鉴别器列具有以下映射:

Map<CompanyNote>(t => t.Requires("type").HasValue("company"));
Map<OrderNote>(t => t.Requires("type").HasValue("order"));

type的数据库类型是char(18) . EF 生成 sql 就好像它的 nchar :

SELECT /* columns */
FROM [dbo].[notes] AS [Extent1]
WHERE [Extent1].[type] = N'company'

那个N这是一个问题,因为该表有数千行并且它阻止 SQL 使用索引。我需要这样查询:

SELECT /* columns */
FROM [dbo].[notes] AS [Extent1]
WHERE [Extent1].[type] = 'company'

这是我到目前为止尝试过的:

  • 添加 Type属性并将其映射 Property(t => t.Type).IsFixedLength().HasMaxLength(18).IsUnicode(false);
  • 将列配置添加到继承映射中 Map<CompanyNote>(t => t.Requires("type").HasValue("company").IsFixedLength().HasMaxLength(18).IsUnicode(false));

这两种改变都没有什么不同。不幸的是,我无法将数据库列类型更改为 nchar .

我如何告诉 Entity Framework 鉴别器列的类型是 char ?

更新:这是一个完整的例子

[TestFixture]
public class TphMappingFixture
{
    [Test]
    public void CompanyNotesQueryShouldNotHaveUnicodeDiscriminator()
    {
        string sql;
        using (TphTestContext context = new TphTestContext())
        {
            sql = context.CompanyNotes.ToString();
        }

        Console.WriteLine(sql);

      /* sql is:
        SELECT 
        '0X0X' AS [C1], 
        [Extent1].[id] AS [id], 
        [Extent1].[text] AS [text]
        FROM [dbo].[notes] AS [Extent1]
        WHERE [Extent1].[type] = N'company'
      */

        Assert.That(!sql.Contains("N'company'"));
    }
}

public abstract class TphTestNote
{
    public int Id { get; set; }
    public string Text { get; set; }
}

public class TphTestCompanyNote : TphTestNote
{
}

public class TphTestOrderNote : TphTestNote
{
}

public class TphTestNoteMap : EntityTypeConfiguration<TphTestNote>
{
    public TphTestNoteMap()
    {
        HasKey(t => t.Id);

        Property(t => t.Text)
            .HasMaxLength(254)
            .IsUnicode(false);

        ToTable("notes");

        Property(t => t.Id).HasColumnName("id");
        Property(t => t.Text).HasColumnName("text");

        Map<TphTestCompanyNote>(t => t.Requires("type").HasValue("company").IsUnicode(false));
        Map<TphTestOrderNote>(t => t.Requires("type").HasValue("order").IsUnicode(false));
    }
}

public class TphTestContext : DbContext
{
    static TphTestContext()
    {
        Database.SetInitializer<TphTestContext>(null);
    }

    public DbSet<TphTestCompanyNote> CompanyNotes { get; set; }
    public DbSet<TphTestOrderNote> OrderNotes { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new TphTestNoteMap());
    }
}

最佳答案

我仍然不确定为什么我看到的结果与@Slauma 不同,但我终于找到了适合我的东西。我在继承映射中将列类型显式设置为 char

Map<TphTestCompanyNote>(t => t.Requires("type")
                              .HasValue("company")
                              .HasColumnType("char"));

Map<TphTestOrderNote>(t => t.Requires("type")
                            .HasValue("order")
                            .HasColumnType("char"));

以及生成的 SQL:

SELECT 
'0X0X' AS [C1], 
[Extent1].[id] AS [id], 
[Extent1].[text] AS [text]
FROM [dbo].[notes] AS [Extent1]
WHERE [Extent1].[type] = 'company'

关于entity-framework-4 - TPH 继承映射使用 nchar (N'value') 而不是 char ('value' ) 作为鉴别器列值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11886387/

相关文章:

c# - 代码首先多对多设置表名称

c# - 可以在 EF 代码第一次迁移种子方法中设置断点吗?

.net - Entity Framework 6 with SQLite 3 Code First - 不会创建表

c# - 如何首先在 EF 代码中处理一个数据库在多个数据库上下文中使用的一个类?

mysql - 使用 LINQ 获取具有多对多关系的子表的所有记录

c# - 如何在 Entity Framework 4.0 中删除多对多循环?

c# - DbContext 表映射

c# - Entity Framework 4 : convert a string condition to a lambda expression?

wcf - 通过 API 公开 Entity Framework 类——好主意还是坏主意

c# - 代码首先拒绝级联删除实体