gpt4 book ai didi

c# - 加载实体实例需要超过 1 秒

转载 作者:太空宇宙 更新时间:2023-11-03 14:40:48 29 4
gpt4 key购买 nike

我在 EF 中遇到了一件有趣的事情。如果我们使用基础实体获取子实体,加载实体将花费更多时间。我的模型如下所示:

public abstract class BaseDocument
{
public Guid Id { get; set; }
public string Name { get; set; }
}

public abstract class ComplexDocument : BaseDocument
{
public string AuthorName { get; set; }
}

public abstract class SimpleDocument : BaseDocument
{
public int Level { get; set; }
}

public abstract class OfficeDocument : ComplexDocument
{
public string OfficeName { get; set; }
}

public abstract class ClassDocument : SimpleDocument
{
public string HeadName { get; set; }
}

public class WordDocument : OfficeDocument
{
public int PagesCount { get; set; }
}

public class ExcelDocument : OfficeDocument
{
public int SheetsCount { get; set; }
}

public class TextDocument : ClassDocument
{
public int LinesCount { get; set; }
}

我正在使用 TPT 方法。这是继承树 inheritance tree这是我的上下文类:

public class Context : DbContext
{
public Context() : base(@"Server=(localdb)\MSSQLLocalDB;Database=EFSIX;Trusted_Connection=True;")
{
Database.CreateIfNotExists();
}
public DbSet<BaseDocument> BaseDocuments { get; set; }
public DbSet<ComplexDocument> ComplexDocuments { get; set; }
public DbSet<SimpleDocument> SimpleDocuments { get; set; }
public DbSet<OfficeDocument> OfficeDocuments { get; set; }
public DbSet<ClassDocument> ClassDocuments { get; set; }
public DbSet<ExcelDocument> ExcelDocuments { get; set; }
public DbSet<WordDocument> WordDocuments { get; set; }
public DbSet<TextDocument> TextDocuments { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<BaseDocument>().ToTable("BaseDocuments");
modelBuilder.Entity<ComplexDocument>().ToTable("ComplexDocuments");
modelBuilder.Entity<SimpleDocument>().ToTable("SimpleDocuments");
modelBuilder.Entity<OfficeDocument>().ToTable("OfficeDocuments");
modelBuilder.Entity<ExcelDocument>().ToTable("ExcelDocuments");
modelBuilder.Entity<WordDocument>().ToTable("WordDocuments");
modelBuilder.Entity<ClassDocument>().ToTable("ClassDocuments");
modelBuilder.Entity<TextDocument>().ToTable("TextDocuments");
}
public IQueryable<T> GetEntities<T>() where T : class
{
return Set<T>();
}
}

我正在创建一些数据:

static void CreateTestData()
{
using (Context context = new Context())
{
for (int i = 0; i < 20; i++)
{
ExcelDocument excel = new ExcelDocument()
{
Id = Guid.NewGuid(),
AuthorName = $"ExcelAuthor{i}",
Name = $"Excel{i}",
OfficeName = $"ExcelOffice{i}",
SheetsCount = (i + 1) * 10
};
context.ExcelDocuments.Add(excel);

WordDocument word = new WordDocument()
{
Id = Guid.NewGuid(),
AuthorName = $"WordAuthor{i}",
Name = $"Word{i}",
OfficeName = $"WordOffice{i}",
PagesCount = (i + 2) * 10
};
context.WordDocuments.Add(word);

TextDocument text = new TextDocument()
{
Id = Guid.NewGuid(),
Name = $"Text{i}",
LinesCount = (i + 3) * 10,
HeadName = $"Head{i}",
Level = i + 5
};
context.TextDocuments.Add(text);
}
context.SaveChanges();
}
}

我做了一些从数据库中获取 WordDocument 的方法。其中一个使用 BaseDocument,另一个使用 WordDocument。两者都返回 20 个 WordDocument 实例:

 static long ReadBaseDoc()
{
using (Context context = new Context())
{
var words= context.GetEntities<BaseDocument>().Where(e => e.Name.StartsWith("Word"));
Stopwatch stopwatch = Stopwatch.StartNew();
var instacnes = excel.ToList();
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}
}
static long ReadWordDoc()
{
using (Context context = new Context())
{
var words = context.GetEntities<WordDocument>().Where(e => e.Name.StartsWith("Word"));
Stopwatch stopwatch = Stopwatch.StartNew();
var instacnes = words.ToList();
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}
}

我单独测试了 moth 方法,多次,平均方法 ReadWordDoc 需要 25ms,方法 ReadBaseDoc 需要 52ms(实例是相同的)。现在这不是太大的问题,但是当我们有复杂的继承时,它需要超过 1 秒。我创建了 10 个类并继承自 BaseDocument。之后我执行了 ReadBaseDocReadWordDoc 方法。 ReadWordDoc 耗时 25 毫秒,ReadBaseDoc 耗时 1023 毫秒。实例是一样的,为什么ReadBaseDoc需要更多的时间?在 EF 中避免此类问题的更好方法是什么?

最佳答案

看看here .有多种方法可以使 EF 更快,但在那些复杂的场景中,ORM 只会产生比它解决的问题更多的问题。

在您的情况下,一种方法是尝试将继承更改为 TablePerType,也许它会快一点。

其他方法是定位慢请求并为它们使用 Dapper - 它会快得多。

最后一种方法是创建一个带有实时缓存的存储库,将完整的数据库加载到内存中并保持最新——这应该是应用程序中的单例。如果您有多个应用程序使用同一个数据库,则需要连接数据更改触发器。

一般来说,对于像您这样的缓慢(且相对简单)的查询,我会说使用 Dapper + AutoMapper。保持 EF 以便您的数据库与您的类保持同步,但不要依赖它进行查询。

如果你真的想坚持使用 ORM,我认为你需要切换 nHibernate。我自己还没有尝试过,但从我读到的内容来看,它几乎在所有可能的方面都很出色,包括性能和启动时间。

关于c# - 加载实体实例需要超过 1 秒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56946573/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com