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();
}