繁体   English   中英

Net Core:通用存储库主 ID 实体框架中的关键性能

[英]Net Core: Generic Repository Primary Id Key Performance in Entity Framework

我们正在审查通用存储库模式中的两种不同方法。 目前,想要将主键映射到 Id。 这样做的目的是映射到使用 Id 的通用存储库接口。 下面提供两种解决方案。

.FindPrimaryKey().Properties 对性能有何影响。 在尝试查找主键时,它是否会导致数据库表上的模式锁定? 它会导致任何应用程序缓慢吗?

它与部分类方法解决方案 2 的性能相比如何? 什么选择在性能方面更好?

注意:架构师要求在工作场所使用存储库模式,因此实施它。 知道围绕这个问题有争论,但不是我的呼吁。

脚手架模型示例:

namespace Datatest
{
    public partial class Property
    {
        public int Property { get; set; }
        public int DocumentId { get; set; }
        public string Address { get; set; }
    }
}

所有表的示例通用基础存储库:

    public T Get(int id)
    {
        return Table.Find(id);
    }
    public async Task<T> GetAsync(int id)
    {
        return await Table.FindAsync(id);
    }
    public T Single(Expression<Func<T, bool>> predicate)
    {
        return All.Single(predicate);
    }
    public async Task<T> SingleAsync(Expression<Func<T, bool>> predicate)
    {
        return await All.SingleAsync(predicate);
    }
    public T FirstOrDefault(int id)
    {
        return All.FirstOrDefault(CreateEqualityExpressionForId(id));
    }

解决方案 1:FindPrimaryKey()

使用实体框架的 C# 中的通用存储库

使用 EF FindPrimaryKey()

var idName = _context.Model.FindEntityType(typeof(TEntity))
        .FindPrimaryKey().Properties.Single().Name;

解决方案2:部分类映射

Net Core:为所有表创建通用存储库接口 ID 映射自动代码生成

public partial class Property: IEntity
{
    [NotMapped]
    public int Id { get => PropertyId; set => PropertyId = value; }
}

关于第一种方法(使用 EF Core 元数据服务):

首先,EF Core 是 ORM(对象关系映射器),这里最重要的是Mapper

其次,它使用所谓的基于代码的模型,这意味着所有映射都是由代码提供的,而不是由实际数据库提供的(即使模型是通过对现有数据库进行逆向工程创建的)。

简而言之,EF Core 在运行时创建一个内存数据结构,其中包含有关类和属性的信息(元数据)以及它们到数据库表、列和关系的映射。 所有这些信息都基于纯代码模型——实体类、约定、数据注释和流畅的配置。

所有 EF Core 运行时行为都基于该元数据模型。 EF Core 在构建查询、将查询结果映射到对象、链接导航属性、生成创建/更新/删除命令及其执行顺序、在获取真正的自动生成的主要键值后更新临时 FK 属性值等时在内部使用它。

因此,元数据模型和发现服务(方法)使用优化的数据结构并且(必须)非常高效。 同样,涉及数据库操作。

所以第一种方法非常有效。 与实际的查询构建、执行和具体化相比,通过元数据服务获取 PK属性名称的性能影响可以忽略不计。

此外,第一种方法的性能类似于您在另一种方法中使用的 EF Core Find方法。 请注意,在调用Find方法时,您只传递 PK 值而不是属性。 所以方法实现应该知道如何构建Where表达式,对吗? 它在内部所做的与建议的代码段非常相似。


关于第二种方法:

它根本没有可比性,因为它不起作用。 可以使用基类/接口,但HasColumnName是映射了实际的属性名称 - 就像所有类都具有Id属性一样,并且使用[Column]数据注释或HasColumnName fluent API 将其映射到数据库表中的不同列名称

在您的示例中, Id属性为[NotMapped] (忽略)。 这意味着 EF Core 无法映射到表列。 您通过代码(属性 getter/setter)映射到另一个属性的事实并不重要。 EF Core不是(反)编译器,它看不到您的代码,因此无法将使用此类属性的 LINQ 查询转换为 SQL。

在 EF Core 2.x 中,这会导致 客户端评估(效率非常低,读取整个表并在内存中应用过滤器),或者如果客户端评估配置为这样做,则会导致异常。 而在 EF Core 3.0+ 中,它将始终是一个例外

因此,如果您不删除诸如PropertyId类的PropertyId映射属性Id (这对于“数据库优先”模型来说很困难),则应避免使用第二种“方法”。 即使您可以映射实际的Id属性,您所节省的时间也只是几毫秒。 再说一次,在使用Find您不必担心性能,何必为使用相同(或相似)方法的方法而烦恼。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM