【发布时间】:2012-08-09 15:06:42
【问题描述】:
我正在使用现有数据库并使用 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());
}
}
【问题讨论】:
-
我复制并粘贴了您的模型。我得到了完全相同的查询,但使用的是
WHERE [Extent1].[type] = 'company'。你到底使用什么版本的EF?以及什么数据库和数据库版本?顺便说一句:如果您没有将 DB 初始化程序设置为null,由于 EF 4.3(.1?) 中的错误,您会得到一个异常:stackoverflow.com/a/10020023/270591 -
这很奇怪。我有 EF 4.3.1.0 和 SQL Server 2005。我的模型中没有上下文的连接字符串,而且它实际上从未命中数据库,所以我不确定它是否重要。
-
如果您没有提供连接字符串(也没有上下文构造函数参数),EF 使用
System.Data.SqlClient提供程序(称为“.NET Framework Data Provider for SQL Server”)并尝试连接到 @ 987654340@ 数据库实例。该提供程序适用于 SQL Server 2005 及更高版本,并且应该生成相同的 SQL(在我的理解中)。如果您使用了另一个提供程序,这将很重要(即使没有访问数据库),因为另一个提供程序可以生成其他 SQL。您使用的是 .NET 4.0 吗?还是 4.5? -
.NET 4.0。我没有意识到它正在连接到我本地机器上的
.\SQLEXPRESS(我通过停止服务并获得 ProviderIncompatibleException 来确认)。那个版本的 SQL Server 是 2008。 -
@Slauma,我不确定为什么使用相同的代码和相同版本的 EF 会看到不同的结果,但我发现了其他可行的方法。看我的回答。
标签: entity-framework-4 ef-code-first