【问题标题】:Can an Entity Be Associated By More Than 1 Entity?一个实体可以与多个实体关联吗?
【发布时间】:2012-10-22 02:15:08
【问题描述】:

假设我有以下实体及其上下文配置设置如下。为简洁起见,我省略了很多属性:

public class Company {
    public int Id { get; set; }
    public Location Location { get; set; }
}

public class Customer {
    public int Id { get; set; }
    public Location Location { get; set; }
}

public class Location {
    public int Id { get; set; }
}

public sealed class EntityDefaultContext : DbContext {
    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.Entity<Company>().HasKey(m => m.Id).ToTable("Company");
        modelBuilder.Entity<Company>().Property(m => m.Id).HasColumnName("Id");
        modelBuilder.Entity<Company>().HasRequired(m => m.Location).WithRequiredDependent().Map(m => m.MapKey("LocationId"));

        modelBuilder.Entity<Customer>().HasKey(m => m.Id).ToTable("Customer");
        modelBuilder.Entity<Customer>().Property(m => m.Id).HasColumnName("Id");
        modelBuilder.Entity<Customer>().HasRequired(m => m.Location).WithRequiredDependent().Map(m => m.MapKey("LocationId"));

        modelBuilder.Entity<Location>().HasKey(m => m.Id).ToTable("Location");
        modelBuilder.Entity<Location>().Property(m => m.Id).HasColumnName("Id");
    }
}

如您所见,Company 和 Customer 实体都持有对 Location 实体的引用。我相信通常会发生的事情。

正如您所见,我为此设置了数据库上下文。但是 EF 生成的 SQL 效率非常低:

SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[LocationId] AS [LocationId], 
    [Extent3].[Id] AS [Id1]
FROM
    [dbo].[Customer] AS [Extent1]
LEFT OUTER JOIN [dbo].[Company] AS [Extent2] ON [Extent1].[LocationId] = [Extent2].[LocationId]
LEFT OUTER JOIN [dbo].[Company] AS [Extent3] ON [Extent1].[LocationId] = [Extent3].[LocationId]
LEFT OUTER JOIN [dbo].[Company] AS [Extent4] ON [Extent1].[LocationId] = [Extent4].[LocationId]

这是在我执行以下操作时生成的:

var q = from c in defaultContext.Set<Customer>().Include(m => m.Location)
        select c;

我这样做是出于与问题无关的原因。奇怪的是,如果我只将 Location 实体配置为仅由 Customer 实体关联,那么这里是 SQL:

SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[LocationId] AS [LocationId]
FROM
    [dbo].[Customer] AS [Extent1]
INNER JOIN [dbo].[Location] AS [Extent2] ON [Extent1].[LocationId] = [Extent2].[Id]

这是我所期望的。这让我思考。 EF 不支持这种情况吗?怎么可能没有?

提前致谢。

【问题讨论】:

  • 这不可能。为什么在查询客户时将公司加入查询?没有返回公司的向后导航属性。事实上, Location 甚至不是查询的一部分,尽管您将其包括在内。所以要么你提出了错误的查询,要么发生了一些非常奇怪的事情。请注意查询如何在选择字段中列出 Extent3,但在 From 中未定义 Extent3?
  • 为什么将其映射为一对一?尝试将其映射为一对多,其中位置可以有多个客户和公司。
  • @MystereMan 你是对的。那是我的错误。我为第二个示例发布了不正确的代码 sn-p。我现在修好了。
  • @LadislavMrnka 天才!我完全误解了 API。我认为“WithRequiredDependent”方法只是建立了一个必需的属性。我不知道它建立了1:1的关系。我把它改成使用“WithMany”,它就像一个魅力!如果您将此作为答案发布,我很乐意将其标记为正确答案。非常感谢您的帮助。

标签: c# entity-framework ef-code-first entity-framework-5


【解决方案1】:

您的原始映射使用一对一关系。这总是会导致一些特殊的行为。此外,它还有一些其他要求才能正常工作。您可能想要的是CustomerLocationCompanyLocation 之间的一对多关系。将WithRequiredDependent 更改为WithMany,它应该可以工作。

【讨论】:

  • 谢谢。 “某些特殊行为”是否记录在任何地方?我查看了 MSDN 上的 RequiredNavigationPropertyConfiguration.WithRequiredDependent 并没有阅读任何有关此行为的信息。
猜你喜欢
  • 1970-01-01
  • 2015-07-19
  • 1970-01-01
  • 2015-03-07
  • 2011-09-17
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
  • 2016-01-13
相关资源
最近更新 更多