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

Entity framework 4 TPH继承映射使用nchar(N'value')而不是char('value')作为鉴别器列值,entity-framework-4,ef-code-first,Entity Framework 4,Ef Code First,我正在使用一个现有的数据库,并首先使用EF4.3代码。我有一个如下所示的实体层次结构,其中Note是基类: Note - CompanyNote - OrderNote - etc 我正在使用具有以下映射的鉴别器列: Map<CompanyNote>(t => t.Requires("type").HasValue("company")); Map<OrderNote>(t => t.Requires("type").HasValue("orde

我正在使用一个现有的数据库,并首先使用EF4.3代码。我有一个如下所示的实体层次结构,其中Note是基类:

Note
  - CompanyNote
  - OrderNote
  - etc
我正在使用具有以下映射的鉴别器列:

Map<CompanyNote>(t => t.Requires("type").HasValue("company"));
Map<OrderNote>(t => t.Requires("type").HasValue("order"));
这是一个问题,因为这个表有数千行,它阻止SQL使用索引。我需要查询以这样看:

SELECT /* columns */
FROM [dbo].[notes] AS [Extent1]
WHERE [Extent1].[type] = 'company'
以下是我迄今为止所尝试的:

添加类型属性并将其映射为 Propertyt=>t.Type.IsFixedLength.HasMaxLength18.IsUnicodalse; 使用将列配置添加到继承映射 Mapt=>t.requireType.HasValuecompany.IsFixedLength.HasMaxLength18.IsUnicodalse; 这两个变化都没有改变。不幸的是,我无法将数据库列类型更改为nchar

我如何告诉EntityFramework鉴别器列的类型是char

更新:这里有一个完整的例子


我无法在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;
                }
            }
        }
    }
}

这个测试和您的代码有什么不同?

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

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

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

一个区别是我使用ctx.Set而不是ctx.Set.OfType进行查询。我将整理一个最小但完整的示例,并更新我的问题。@jrummell:如果我将LINQ查询更改为您的查询,我将得到相同的SQL。我复制并粘贴了您的模型。我得到了完全相同的查询,但其中[Extent1].[type]='company'。您使用的EF的具体版本是什么?什么数据库和数据库版本?顺便说一句:如果您没有将DB初始值设定项设置为null,您将由于EF 4.3.1中的错误而得到一个异常:这很奇怪。我有EF4.3.1.0和SQLServer2005。我的模型中没有上下文的连接字符串,而且它从来没有实际命中数据库,因此,我不确定这是否重要。如果您没有提供连接字符串和上下文构造函数参数,EF将使用System.Data.SqlClient提供程序(称为SQL Server的.NET Framework数据提供程序)并尝试连接到。\SQLEXPRESS DB实例。该提供程序适用于SQLServer2005及更高版本,据我所知,应该生成相同的SQL。如果您使用了另一个提供程序,那么即使不触及数据库,这也很重要,因为另一个提供程序可以生成其他SQL。您正在使用.NET4.0吗?或4.5?.NET 4.0。我没有意识到它正在连接到本地计算机上的。\SQLEXPRESS,我通过停止服务并获取ProviderIncompatibleException进行了确认。那个版本的SQL Server是2008版的。@Slauma,我不知道为什么我们在相同的代码和相同版本的EF中看到不同的结果,但我发现了其他一些有效的方法。看我的答案。我也测试过了,但因为它对我的工作方式与你的原始代码相同,我认为这无关紧要,也没有什么区别。真奇怪,为什么这适用于您的映射,而不是原始映射。我不知道原因是什么。
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;
                }
            }
        }
    }
}
Map<TphTestCompanyNote>(t => t.Requires("type")
                              .HasValue("company")
                              .HasColumnType("char"));

Map<TphTestOrderNote>(t => t.Requires("type")
                            .HasValue("order")
                            .HasColumnType("char"));
SELECT 
'0X0X' AS [C1], 
[Extent1].[id] AS [id], 
[Extent1].[text] AS [text]
FROM [dbo].[notes] AS [Extent1]
WHERE [Extent1].[type] = 'company'