有关EF 4.1,代码优先和TPH的性能问题

时间:2011-10-25 08:42:24

标签: entity-framework ef-code-first

我正在尝试使用EF 4.1和代码创建数据模型。 我的Poco课程看起来像这样:

public abstract class AttributeBase
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string AttributeDescription { get; set; }
    public int Length { get; set; }

    public bool AllowNull { get; set; }
    public bool DisplayInWeb { get; set; }

}

public class StringListAttribute : AttributeBase
{
    public ICollection<StringValue> Values { get; set; }        

    public StringListAttribute()
    {
        Values = new List<StringValue>();
    }
}

public class StringValue
{
    public int StringValueId { get; set; }        
    public string Value { get; set; }

}

基本思想是StringListAttribute继承自AttributeBase类(其他类也继承自AttributeBase类,但我没有在这篇文章中包含它们)

StringListAttribute类具有StringValues的集合。 (零对多关系)。我在MyContextExtention类中尝试实现的是,每当我想要数据库中的AttributeBase对象列表时,我想获取所有StringListAttribute对象并一次填充它们的StringValue集合。我不想要任何延迟加载。我希望在尽可能少的查询中尽可能多地检索数据。

我的Context类继承自DbContext,我在BraArkivContext类上创建了一个扩展方法

public class MyContext : DbContext 
{        
    public DbSet<AttributeBase> Attributes { get; set; }        

    public MyContext()
    {
        Configuration.LazyLoadingEnabled = false;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<StringListAttribute>()
                         .HasMany(t=>t.Values).WithOptional().WillCascadeOnDelete();            

        base.OnModelCreating(modelBuilder);   
    }
}

public static class MyContextExtension
{
    private const string Values = "Values";

    public static List<AttributeBase> AttributesWithData1(this MyContext context)
    {
        var attributeBases = new List<AttributeBase>();

        var stringListAttributes = context.Attributes.Include(Values).OfType<StringListAttribute>().ToList();

        attributeBases.AddRange(stringListAttributes);

        return attributeBases;
    }

}

我的测试项目(我正在使用nUnit))没什么好写的,并且包含这些方法:

public class TestHelper
{
     public static StringListAttribute CreateStringListAttribute(string name, int listSize)
    {
        var listAttribute = new StringListAttribute();
        listAttribute.Name = name;

        for (int i = 0; i < listSize; i++)
        {
            var attr1 = new StringValue();
            attr1.Value = String.Format("StringValue_{0}", i);
            listAttribute.Values.Add(attr1);
        }

        return listAttribute;
    }
}

[Test]
public void AttributeBase_GetAllAttributesWithData1()
{            

         //First add some data to the database
        var numberOfObjects = 100;
        var name = "StringListAttribute_ReadMultipleStringsListsFromDb_" + Guid.NewGuid().ToString();
        var listAttributes = TestHelper.CreateStringLists(name, numberOfObjects);

        using (var context = new MyContext())
        {
            foreach (var stringListAttribute in listAttributes)
            {
                context.Attributes.Add(stringListAttribute);    
            }

            context.SaveChanges();
        }

        Stopwatch sw = new Stopwatch()

        var attributes = new List<AttributeBase>();
        using (var context = new MyContext())
        {
            sw.Start();
            attributes = context.AttributesWithData1().ToList();
            sw.Stop();
        }


        Debug.WriteLine(String.Format("Total time for {0} attributes is: {1}.", attributes.Count, sw.Elapsed));
        Assert.IsNotNull(attributes);
}

运行测试方法“AttributeBase_GetAllAttributesWithData1”时执行的sql语句如下所示:

SELECT 
[Project1].[Id] AS [Id], 
[Project1].[C1] AS [C1], 
[Project1].[Name] AS [Name], 
[Project1].[AttributeDescription] AS [AttributeDescription], 
[Project1].[Length] AS [Length], 
[Project1].[AllowNull] AS [AllowNull], 
[Project1].[DisplayInWeb] AS [DisplayInWeb], 
[Project1].[Document_Id] AS [Document_Id], 
[Project1].[C2] AS [C2], 
[Project1].[StringValueId] AS [StringValueId], 
[Project1].[Value] AS [Value], 
[Project1].[StringListAttribute_Id] AS [StringListAttribute_Id]
FROM ( SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[Name] AS [Name], 
[Extent1].[AttributeDescription] AS [AttributeDescription], 
[Extent1].[Length] AS [Length], 
[Extent1].[AllowNull] AS [AllowNull], 
[Extent1].[DisplayInWeb] AS [DisplayInWeb], 
[Extent1].[Document_Id] AS [Document_Id], 
'0X0X' AS [C1], 
[Extent2].[StringValueId] AS [StringValueId], 
[Extent2].[Value] AS [Value], 
[Extent2].[StringListAttribute_Id] AS [StringListAttribute_Id], 
CASE WHEN ([Extent2].[StringValueId] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS     [C2]
FROM  [dbo].[AttributeBases] AS [Extent1]
LEFT OUTER JOIN [dbo].[StringValues] AS [Extent2] ON [Extent1].[Id] = [Extent2].[StringListAttribute_Id]
WHERE [Extent1].[Discriminator] = 'StringListAttribute'
)  AS [Project1]
ORDER BY [Project1].[Id] ASC, [Project1].[C2] ASC

当我在SQL Server Management Studio中运行此sql语句时,它非常快,但实体框架需要很长时间来处理结果并返回填充了数据的poco类。

有没有其他方法来建模AttributeBase,StringListAttribute和StringValue类以及它们之间的关系以减少EF中的处理时间?

0 个答案:

没有答案