【问题标题】:Entity Framework - customize navigation properties to abstract joins实体框架 - 自定义导航属性以抽象连接
【发布时间】:2014-08-01 01:00:10
【问题描述】:

我在这里查看了类似的问题,但没有看到这个特定的场景。

使用EF 6 Code First,我有三个表,A、B和C。关系是A => B = 1:M,B=>C = 1:1

这个模式的最终结果是在 A 和 C 之间存在一个隐含的 1:M。

我不希望实体框架模型的消费者知道 B。理想情况下,他们将拥有从 A 到 C 的 1:M 导航属性(并且我希望能够通过 Web API 显示此实体模型和 OData 作为 IQueryable)

我怎么能这样做?

如果我将自定义 [NotMapped] 属性添加到 C 集合的 A 中,我无法在该属性的 getter 中填充 C,因为实体不知道其上下文。

任何人对如何实现 IQueryable 有任何想法,其中 A 具有到 C 的导航属性并且 B 被“抽象”不存在?

编辑

尝试将以下内容放入代码优先实体 A:

[NotMapped]
public ICollection<C> Cs
{
        get { return this.Bs.Select(b => b.C) as ICollection<C>; }
}

但是得到了这个错误: 导航属性“C”不是类型“A”的声明属性。验证它没有被明确地从模型中排除,并且它是一个有效的导航属性。

谢谢。

【问题讨论】:

  • implicit 1:M between A and C. 是什么意思?你为什么不想通过 B 从 A 到 C 呢?
  • 我正在使用无法更改的旧架构。但是我的服务的消费者不需要知道这些表之间连接的细节。他们真的只关心 A 和 C 之间的关系。实体框架应该能够给消费者一个可查询的实体模型,它隐藏了必须发生的连接的细节。如果我在做 Model-First,我可能会考虑为此使用 DefiningQuery。
  • 如果你想得到一个包含所有C的单个A,你只需要添加带有[NotMapped]属性的Cs属性然后选择查询,var a = db.As.Include(a =&gt; a.Bs.Select(b =&gt; b.C)).FirstOrDefault(a =&gt; a.Id == key);并填写Cs,@987654326 @
  • Yuliam,感谢您的询问。这绝对适用于模型的消费者,但如果我正确阅读您的代码,它仍然需要 EF 模型消费者了解 B。没有地方可以告诉 EF 当访问 C 属性时,它应该运行该查询来填充它。客户会这样做,对吗?
  • 那么您所说的消费者是指使用 dbcontext(odata 控制器)的任何代码吗?不是那些访问 odata 服务 (http://localhost/Products) 的?

标签: c# entity-framework


【解决方案1】:

这是一个例子。

public static class OrderDAL
{
    public static Order Get(int key)
    {
        using (var context = new AppContext())
        {
            var order = context.Orders.Include(a => a.OrderDetails.Select(b => b.Information)).FirstOrDefault(a => a.Id == key);
            // Fills C.
            order.OrderDetailAdditionalInformation = order.OrderDetails.Select(b => b.Information).ToArray();
            // Hides information about B.
            foreach (var information in order.OrderDetailAdditionalInformation)
            { information.OrderDetail = null; }
            order.OrderDetails = null;
            return order;
        }
    }
}
public class AppContext : DbContext
{
    public DbSet<Order> Orders { get; set; }
}
// A
public class Order
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
    public ICollection<OrderDetail> OrderDetails { get; set; }
    [NotMapped]
    public ICollection<OrderDetailAdditionalInformation> OrderDetailAdditionalInformation { get; set; }
}
// B, one A many B
public class OrderDetail
{
    public int Id { get; set; }
    public int Qty { get; set; }
    public string Item { get; set; }
    public int OrderId { get; set; }
    public Order Order { get; set; }
    public OrderDetailAdditionalInformation Information { get; set; }
}
// C, one B one C
public class OrderDetailAdditionalInformation
{
    [ForeignKey("OrderDetail")]
    public int Id { get; set; }
    public int Width { get; set; }
    public int Height { get; set; }
    public int Long { get; set; }
    public OrderDetail OrderDetail { get; set; }
}

【讨论】:

  • 感谢以上。该示例实际上有助于隐藏表 B。我试图找出它适合的位置是在 Web API 或 OData 项目示例中,我有一个表 A 的控制器,我想这样做:@987654322 @ AController 会为此被调用,但由于 Cs 不是导航属性(您只是将其显示为静态方法),我认为无法使此查询起作用,所以感觉我还是很我的提取受限。
  • @RandyMagruder,我想你是对的,Cs 不是图表的一部分,直接对其进行查询是行不通的
猜你喜欢
  • 2020-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-27
  • 1970-01-01
  • 1970-01-01
  • 2016-03-29
  • 2016-05-29
相关资源
最近更新 更多