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



我正在使用现有数据库并使用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

如何告诉实体框架鉴别器列的类型为 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'

我无法在SQL查询中重现Unicode字符串的使用。测试应用程序(使用 EF 4.3.1 的控制台应用):

using System;
using System.Data.Entity;
using System.Linq;
namespace EF43TPH
{
    public abstract class Note
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    public class CompanyNote : Note
    {
        public string ExtendedName { get; set; }
    }
    public class OrderNote : Note
    {
        public string AnotherExtendedName { get; set; }
    }
    public class MyContext : DbContext
    {
        public DbSet<Note> Notes { get; set; }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<CompanyNote>()
                .Map<CompanyNote>(t => t.Requires("type").HasValue("company"));
            modelBuilder.Entity<OrderNote>()
                .Map<OrderNote>(t => t.Requires("type").HasValue("order"));
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>());
            using (var ctx = new MyContext())
            {
                try
                {
                    var query = ctx.Notes.OfType<CompanyNote>();
                    var queryString = query.ToString();
                }
                catch (Exception e)
                {
                    throw;
                }
            }
        }
    }
}

我在queryString中得到的SQL查询是:

SELECT 
'0X0X' AS [C1], 
[Extent1].[Id] AS [Id], 
[Extent1].[Name] AS [Name], 
[Extent1].[ExtendedName] AS [ExtendedName]
FROM [dbo].[Notes] AS [Extent1]
WHERE [Extent1].[type] = 'company'

此测试和您的代码之间有什么不同?

相关内容

最新更新