![](/img/trans.png)
[英]Net Core: Find Primary Key of Entity Framework Core and Reflection
[英]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()
使用 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.