c# - 没有设置器的实体框架核心属性
问题描述
在我的 .net core 3.1 应用程序中,我想将属性封装在某个实体中:
public class Sample : AuditableEntity
{
public Sample(string name)
{
Name = name;
}
public int Id { get; }
public string Name { get; }
}
因此,当我想检查此类 Sample 是否已经存在时,我已经删除了所有公共设置器,因此在我的代码中某处
_context.Samples.Any(r => r.Name == name)
该行导致错误:System.InvalidOperationException: 'No suitable constructor found for entity type 'Sample'. The following constructors had parameters that could not be bound to properties of the entity type: cannot bind 'name' in 'Sample(string name)'.'
.
所以我添加了代码空构造器
public class Sample : AuditableEntity
{
public Sample() { } // Added empty constructor here
public Sample(string name)
{
Name = name;
}
public int Id { get; }
public string Name { get; }
}
现在该行导致错误:System.InvalidOperationException: 'The LINQ expression 'DbSet<Sample>
.Any(s => s.Name == __name_0)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.'
。
但是,如果我将私有集添加到Name
(或公共),那么一切正常(即使没有空构造函数)。
public class Sample : AuditableEntity
{
public Sample(string name)
{
Name = name;
}
public int Id { get; }
public string Name { get; private set; } // added setter, removed empty constructor
}
谁能解释我为什么需要这个setter,例如Id不需要那个setter。
解决方案
这与 Farhad Jabiyev 在评论中提到的反射有关。EF 找不到该属性,它是隐藏的。当您成功时private set
,EF 可以通过反射访问它,因此一切正常。
这可以通过支持字段https://docs.microsoft.com/en-us/ef/core/modeling/backing-field来完成
从上面的链接:支持字段允许 EF 读取和/或写入字段而不是属性。当类中的封装用于限制使用和/或增强应用程序代码访问数据的语义时,这可能很有用,但值应该在不使用这些限制的情况下从数据库读取和/或写入数据库/增强。
这意味着您必须像这样通过流利的 API 将映射添加到您的支持字段。
modelBuilder.Entity<Sample >()
.Property(b => b.Name)
.HasField("_name"); // this would have to be the name of the backing field
要访问自动道具的支持字段,您可以使用 this->是否可以访问自动实现属性后面的支持字段?
我会自己添加它,这样会更容易。所以我的课看起来像这样。您将需要上面的映射,并且映射解决了我的财产是私有的问题。如果没有映射,这将失败。
public class Sample : AuditableEntity
{
private string _name; //now EF has access to this property with the Mapping added
public Sample(string name)
{
_name = name;
}
public int Id { get; }
public string Name => _name;
}
请看一下勒曼的做法-> https://www.youtube.com/watch?v=Z62cbp61Bb8&feature=youtu.be&t=1191
推荐阅读
- gojs - gojs 嵌套 setDataProperty
- sql - 存在查询不返回相关结果
- react-native - 图像绘制中使用的图像比例 react-native
- jquery - 如何让数据表与 Django 模板中的 bootstrap4 选项卡一起使用?
- openapi - 在 OpenAPI 中,如何使引用模式的某些字段成为必需的?
- python - 在图像的特定区域绘制轮廓并在opencv-python中找到最外层的轮廓
- core-data - SwiftUI/CoreData:同时访问0x7f92efc61cb8,但修改需要独占访问
- ios - 显示一个可以复制但不能修改的值 (Swift)
- cypress - 赛普拉斯:如何将 API 响应中的选定属性传递给另一个 API 请求?
- xml - ID 字段上的 DTD