我正在使用现有数据库并使用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());
}
}
答案 0 :(得分:2)
我仍然不确定为什么我看到的结果与@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'
答案 1 :(得分:1)
我无法在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'
此测试与您的代码有什么不同?