实体框架6 TPH继承枚举字段生成慢查询

时间:2016-11-03 15:28:03

标签: performance entity-framework enums casting

我首先使用EF 6.0代码,并在我的项目中使用TPH继承。我看到如果我在我的类中使用enum字段,EF会生成带有强制转换的sql语句。所以我的查询运行速度非常慢,性能下降。如何在我的SQL查询中删除转换?

感谢。

var db = new AppContext();
var p = db.Products.FirstOrDefault(x => x.ProdId == 1);


public enum MyEnum
{
    Field1 = 1,
    Field2 = 2
}

public class Product
{
    [Key]
    public int ProdId { get; set; }

    public string ProdName { get; set; }

    //I run my code with this property and without this property.
    //public MyEnum MyEnum { get; set; }
}

public class Chair : Product
{
    public string ChairProp1 { get; set; }
}

public class Seat : Product
{
    public string SeatProp1 { get; set; }
}

//EF generate this SQL without enum field. This is good SQL statements.
SELECT TOP (1) 
[Extent1].[Discriminator] AS [Discriminator], 
[Extent1].[ProdId] AS [ProdId], 
[Extent1].[ProdName] AS [ProdName], 
[Extent1].[ChairProp1] AS [ChairProp1], 
[Extent1].[SeatProp1] AS [SeatProp1]
FROM [dbo].[Products] AS [Extent1]
WHERE ([Extent1].[Discriminator] IN (N'Chair',N'Seat',N'Product')) AND (1 = [Extent1].[ProdId])


//EF generate this SQL with enum field (myenum). there is alot of casting.i want to remove casting.
SELECT 
[Limit1].[C1] AS [C1], 
[Limit1].[ProdId] AS [ProdId], 
[Limit1].[ProdName] AS [ProdName], 
[Limit1].[MyEnum] AS [MyEnum], 
[Limit1].[C2] AS [C2], 
[Limit1].[C3] AS [C3]
FROM ( SELECT TOP (1) 
    [Extent1].[ProdId] AS [ProdId], 
    [Extent1].[ProdName] AS [ProdName], 
    [Extent1].[MyEnum] AS [MyEnum], 
    CASE WHEN ([Extent1].[Discriminator] = N'Product') THEN '0X' WHEN ([Extent1].[Discriminator] = N'Chair') THEN '0X0X' ELSE '0X1X' END AS [C1], 
    CASE WHEN ([Extent1].[Discriminator] = N'Product') THEN CAST(NULL AS varchar(1)) WHEN ([Extent1].[Discriminator] = N'Chair') THEN [Extent1].[ChairProp1] END AS [C2], 
    CASE WHEN ([Extent1].[Discriminator] = N'Product') THEN CAST(NULL AS varchar(1)) WHEN ([Extent1].[Discriminator] = N'Chair') THEN CAST(NULL AS varchar(1)) ELSE [Extent1].[SeatProp1] END AS [C3]
    FROM [dbo].[Products] AS [Extent1]
    WHERE ([Extent1].[Discriminator] IN (N'Chair',N'Seat',N'Product')) AND (1 = [Extent1].[ProdId])
)  AS [Limit1]

1 个答案:

答案 0 :(得分:0)

看来你错过了鉴别器的配置。您需要指定哪个字段是鉴别器,以及它的类型是什么,

你可以通过这样的流畅api来做到这一点:

public class ChairConfig : EntityTypeConfiguration<Chair>
{
    public ChairConfig()
    {
        this.Map(m => m.Requires(discriminator: "MyEnum").HasValue(MyEnum.Field1));
    }
}

public class SeatConfig : EntityTypeConfiguration<Seat>
{
    public SeatConfig()
    {
        this.Map(m => m.Requires(discriminator: "MyEnum").HasValue(MyEnum.Field2));
    }
}

在查询中,您需要指定要检索的类型:

var db = new AppContext();
var p = db.Products.OfType<Chair>().FirstOrDefault(x => x.ProdId == 1);