在EFCore 3.0中-如何从视图中加入相关的只读无密钥实体,以便加载相关实体

使用.NET EFCore 3.0-查询类型已弃用,现在我们移至Entity Framework Core 3.0中的"Keyless entity type"

我的要求是使用新的HasnoKey()语法将多个只读视图从MS SQL数据库映射到DbContext。

  1. 返回的只读实体必须加载其相关的只读 仅限实体。
  2. 有没有一种方法可以将视图彼此连接并自动加载相关 实体?
  3. 也许还有另一种使用视图和只读实体的方法 除了使用HasnoKey以外?

简单的示例架构,Order有许多OrderItems。如果这两个实体都来自视图,那么订单如何加载其OrderItems?

public class ReadonlyactionOnDb
{
    OrdersDbContext Db; //need to pass in via constructor etc,just for demo code.
    protected void PrintOrderItems()
    {
        var custItems = Db.vOrders.Where(i=> i.CustomerId == 10).SelectMany(i=> i.OrderItems);
        foreach (OrderItemDto i in custItems ) Console.WriteLine(i.ProductName); 
    }           
}

//part of the config shown...
public partial class OrdersDbContext: DbContext
{
    public DbSet<OrderDto> vOrders { get; set; }
    public DbSet<OrderDto> vOrderItems { get; set; }

    protected void OnmodelCreating(ModelBuilder modelBuilder)
    {           
        modelBuilder.Entity<OrderItemDto>().HasnoKey().ToView("vOrderItems ","dbo");

        //how do we automatically load the OrderItems into this?
        modelBuilder.Entity<OrderDto>().HasnoKey().ToView("vOrders","dbo");
    }
}

public class OrderDto
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public ICollection<OrderItemDto> OrderItems { get; set; }
}

public class OrderItemDto
{
    public int Id { get; set; }
    public string ProductName { get; set; }
}

我认为这应该在DbContext实例上实现,我知道以后可以手动加载并加入。

对于此问题,迁移并不重要,因为DBA会对数据库执行自己的更新。

下面是MS Documentation中发现的无密钥实体类型的限制。没有示例的实体导航有点混乱。

  

无键实体类型特征

     

无键实体类型支持许多与以下相同的映射功能   常规实体类型,例如继承映射和导航   属性。在关系存储上,他们可以配置目标   通过流畅的API方法或数据访问数据库对象和列   注释。

     

但是,它们与常规实体类型的不同之处在于:

     

无法定义键。

     

永远不会跟踪DbContext中的更改,因此永远不会   在数据库上插入,更新或删除。

     

从未被惯例发现。

     

仅支持部分导航映射功能,   具体来说:

     

他们可能永远不会成为恋爱关系的主要目的。

     

他们可能没有到拥有实体的导航

     

它们只能包含指向以下内容的参考导航属性   常规实体。

     

实体不能包含无键实体类型的导航属性。

     

需要使用.HasnoKey()方法调用进行配置。

     

可以映射到定义查询。定义查询是一个查询   在模型中声明为无密钥实体的数据源   类型。

wunbin 回答:在EFCore 3.0中-如何从视图中加入相关的只读无密钥实体,以便加载相关实体

您无法查询订单,然后包含订单项。但是您可以查询所有订单项,其中父订单符合您的条件,然后包括父记录。

我最近发现了一种设计模式,其中“无键实体”仅包含其他数据库实体的主键。并为其定义了导航属性。

public class OrderDetailKeys{
    public int OrderId { get; set; }
    public int OrderDetailId { get; set; }
    public virtual Order Order { get; set; }
    public virtual OrderDetail OrderDetail { get; set; }
}

modelBuilder.Entity<OrderDetailKeys>(entity => {
    entity.HasNoKey();
    entity.ToView(null); // or real view name
    entity.HasOne(e => e.Order)
        .WithOne()
        .HasForeignKey<OrderDetailKeys>(e => e.OrderId);
    entity.HasOne(e => e.OrderDetail)
        .WithOne()
        .HasForeignKey<OrderDetailKeys>(e => e.OrderDetailId);
}

这样,您可以使用数据库视图或FromRawSql来定义可重复使用的结果集中有哪些记录。

    public static IQuerable<OrderDetailKeys> ComplexQuery(DbContext context) => 
        context.Set<OrderDetailKeys>()
            .FromRawSql("select OrderId,Id as OrderDetailId from OrderDetail where <complex sql condition here>");

在每个使用此结果集的地方,都可以在Where条件下进一步限制结果。然后仅IncludeSelect所需的列。

    var details = ComplexQuery(context)
        .Where(k => k.Order.CustomerId = ...)
        .Include(k => k.OrderDetail)
        .ToListAsync();

EF将使用视图或原始sql作为from子句中的子查询。然后围绕该联接构建其他表。

您无法说服EF生成的SQL的丑陋之处被封装在一个位置中。而且,您不会最终为每个视图重复实际表的列模式。

,

基于以下原因,无法完成此操作,因为订单将成为您的本金:

  
      
  • 仅支持导航映射功能的子集,特别是:      
        
    • 他们可能永远不会成为恋爱关系的主要目的。
    •   
  •   
本文链接:https://www.f2er.com/3151470.html

大家都在问