【问题标题】:How to reference an entity from different entity types in EF Core如何在 EF Core 中引用来自不同实体类型的实体
【发布时间】:2021-06-07 19:52:31
【问题描述】:

在我的应用程序中,我需要对链接的概念进行建模。它包含一个名称、一个描述,当然还有一个 URL。 为简单起见,假设我有 2 个可以有许多链接的实体:公司和项目。

如果我将 ICollection of Link(泛型)添加到 Company 实体,EF 将在 Link 表中添加从 Link 到 Company 的 FK。如果我将 ICollection of Link 添加到项目实体中,也会发生同样的情况。

我希望 Link 表完全不知道“谁”可能正在引用它的记录,同时,能够从任何需要的地方引用 Link 对象。

这可能吗?

谢谢!

【问题讨论】:

    标签: entity-framework-core


    【解决方案1】:

    我知道的唯一方法是使用主密钥。在此示例中,我将使用 Link 和 Company。您指出的模型:

    public class Link
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public string URL { get; set; }
        public string CompanyName { get; set; }
    }
    

    我添加了 CompanyName,稍后会详细介绍。

    public class Company
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public ICollection<Link> Links { get; set; }
    }
    

    因此,您可能已经发现,即使子类中没有明确定义整数 FK 属性,EF Core 仍然会在数据库中创建它。 (据我所知)拥有一张完全不知道它与其他人的关系的表是不可能的。但是,使用主键,您可以将 FK 设置为引用父类中的属性而不是主键,为此我将CompanyName 添加到Link。它将引用Company 中的Name 属性并使用它来填充其值。这是您需要在 DbContext 类中进行的映射:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Link>()
            .HasOne<Company>()
            .WithMany(c => c.Links)
            .HasForeignKey(l => l.CompanyName)
            .HasPrincipalKey(c => c.Name);
    }
    

    这是应用迁移后生成的数据库架构 (SQL Server):

    这是我用来测试的数据:

    var newCompanies = new List<Company>()
    {
        new Company()
        {
            Name = "EF Core Enterprises",
            Links = new List<Link>()
            {
                new Link()
                {
                    Name = "Introduction",
                    Description = "The EF Core 101",
                    URL = "https://efcore.com/intro"
                },
                new Link()
                {
                    Name = "Mapping",
                    Description = "Mapping classes to database objects",
                    URL = "https://efcore.com/mapping"
                },
                new Link()
                {
                    Name = "Change Tracker",
                    Description = "Deep dive into EF Core's object tracking mechanism",
                    URL = "https://efcore.com/changetracker"
                }
            }
        },
        new Company()
        {
            Name = "ASP.NET Core Inc.",
            Links = new List<Link>()
            {
                new Link()
                {
                    Name = "Authentication",
                    Description = "Authentication Basics",
                    URL = "https://asp-net-core.com/auth"
                },
                new Link()
                {
                    Name = "Routing",
                    Description = "Configure routing for web apps",
                    URL = "https://asp-net-core.com/routing"
                },
                new Link()
                {
                    Name = "API",
                    Description = "Create a REST API with ASP.NET Core",
                    URL = "https://asp-net-core.com/API"
                }
            }
        }
    };
    
    context.Companies.AddRange(newCompanies);
    context.SaveChanges();
    

    那么,是否可以使用Include() 为公司急切加载链接?是的,没有什么不同。

    var companies = context.Companies
                        .Include(c => c.Links)
                        .ToList();
    
    foreach (var company in companies)
    {
        foreach (var link in company.Links)
        {
            Console.WriteLine($"{link.CompanyName} --> {link.Name} at {link.URL}");
        }
    }
    

    还有输出:

    EF Core Enterprises --> Introduction at https://efcore.com/intro
    EF Core Enterprises --> Mapping at https://efcore.com/mapping
    EF Core Enterprises --> Change Tracker at https://efcore.com/changetracker
    ASP.NET Core Inc. --> Authentication at https://asp-net-core.com/auth
    ASP.NET Core Inc. --> Routing at https://asp-net-core.com/routing
    ASP.NET Core Inc. --> API at https://asp-net-core.com/API
    

    抱歉,篇幅太长,我只想尽可能清楚地解释所有内容。这是有关relationships 的文档。我希望你觉得这很有用。

    【讨论】:

    • 我的巴西朋友,感谢您的友好回复,但恐怕我会面临同样的问题,现在只是使用不同的属性从 Link 表中引用 Company 表。有几个实体可以“拥有”链接,所以我最终会引用它们中的每一个。我想我将不得不考虑一个非标准的解决方案。来自乌拉圭的亲切问候!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-01
    • 2019-05-09
    • 2023-03-07
    • 2022-01-25
    • 1970-01-01
    相关资源
    最近更新 更多