私は既存のデータベースで作業しており、EF4.3コードファーストを使用しています。次のようなエンティティ階層があります。ここで、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
。
識別子列がタイプであることをEntityFrameworkに伝えるにはどうすればよい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());
}
}