C# 我如何解决一个问题;不要在构造函数中调用可重写的方法;虚拟实体框架对象的警告?
我使用的是实体框架,希望在属性上使用延迟加载,因此我将属性设置为虚拟的 例如:C# 我如何解决一个问题;不要在构造函数中调用可重写的方法;虚拟实体框架对象的警告?,c#,.net,entity-framework,C#,.net,Entity Framework,我使用的是实体框架,希望在属性上使用延迟加载,因此我将属性设置为虚拟的 例如: public class Child { public string Name { get; set; } } public class Parent { public Parent() { Child = new Child(); } public virtual Child Child { get; set; } } 当我这样做时,我会得到一个警告:
public class Child
{
public string Name { get; set; }
}
public class Parent
{
public Parent()
{
Child = new Child();
}
public virtual Child Child { get; set; }
}
当我这样做时,我会得到一个警告:
我想删除此警告,但如果我将Parent
标记为sealed
我会得到预期的错误:
Severity Code Description Project File Line Suppression State
Error CS0549 'Parent.Child.get' is a new virtual member in sealed class 'Parent' Project C:\Parent.cs 24 N/A
因此,如何解决此警告(而不忽略它)并仍然使用
virtual
?在属性上使用初始值设定项而不是构造函数
public class Parent
{
public virtual Child Child { get; set; } = new Child();
}
编辑:关于上述内容
…有时我需要为中的子项设置属性
构造器
简单的规则是“你可能不应该”。实体的作用是表示该实体的数据状态,仅此而已。初始化实体“图”不应该在顶级实体的构造函数中完成,而应该使用工厂模式。例如,我使用一个带有EF的存储库模式,我不仅管理getter,还充当工厂,提供创建方法,以及处理软删除场景中的删除。这有助于确保具有依赖关系的实体始终以“最小完整”和有效状态创建
即使是上面的例子,我也会说是一个坏例子。即使它没有触发编译器警告,父级构造点处的实体也没有处于完整有效的状态。如果我要做以下事情:
使用(var context=new MyContext())
{
var parent=新父级();
parent.Name=“我自己”;
SaveChanges();
}
如果父级自动初始化子级,则SaveChanges将希望保存新的子级,并且没有任何东西可以确保子级上的所有必填字段都已设置,则SaveChanges调用将失败。孩子的状态不够完整
我唯一提倡自动初始化的地方是集合:
public class Parent
{
public virtual ICollection<Child> Children { get; internal set; } = new List<Child>();
}
那将是幸福的。或者我可以在调用SaveChanges之前继续设置订单上的可用信息。我的OrderRepository不会有任何业务逻辑,因为业务逻辑可能依赖于客户机的配置,而存储库没有必要知道或关心这一点;但是它可能有一个类似IOrderValidator的依赖项来传递新提出的订单,业务逻辑可以运行到该订单,以断言该订单足够有效,可以保存。repostory/factory断言它足够完整,但它可以绑定到业务逻辑中的验证器,以断言它足够有效。(即最小/最大订单量/价值等)
这与DDD相结合,在DDD中,我将所有setter设置为internal
,并对我的实体使用操作方法,这有助于控制确保我的实体始终保持在完整状态。我猜这是您试图通过使用构造函数来确保的,因此我想我将以上面的示例为例,提供一些可能的想法和替代方案来实现这一点。virtual与延迟加载无关。这是一个继承问题,主要发生在编译时。具体来说,它允许以后过度渲染。请注意,这有一个专用类型<代码>惰性[T]
是惰性初始化的工具:@Christopher-No,实体框架惰性加载,而不是惰性初始化。需要虚拟属性来允许EF生成代理,以便在访问关联实体时,根据需要自动查询关联实体。这消除了警告,但有时我需要在构造函数中为子项设置属性,然后,Walnsii把答案扩展到围绕要处理细节的选项上。
public class Parent
{
public virtual ICollection<Child> Children { get; internal set; } = new List<Child>();
}
public Order CreateOrder(int customerId, IEnumerable<OrderedProductViewModel> orderedProducts)
{
if (!orderedProducts.Where(x => x.Quantity > 0).Any())
throw new ArgumentException("No products selected.");
var customer = Context.Customers.Single(x => x.CustomerId == customerId);
var products = Context.Products.Where(x => orderedProducts.Where(o => o.Quantity > 0).Select(o => o.ProductId).Contains(x.ProductId)).ToList();
if (products.Count() < orderedProducts.Count())
throw new ArgumentException("Invalid products included in order.");
var order = new Order
{
Customer = customer,
OrderLines = orderedProducts.Select(x => new OrderLine
{
Product = products.Single(p => p.ProductId == x.ProductId),
Quantity = x.Quantity
}
}
Context.Orders.Add(order);
return order;
}
using (var contextScope = ContextScopeFactory.Create())
{
var order = OrderRepository.Create(selectedCustomerId, selectedProducts);
contextScope.SaveChanges();
}