如何在Entity Framework Core中设置实体关系

8

在EF Core中,我们有3个表:

  1. 新闻(News)
  2. 物品(Items)
  3. 链接(Links)

除了新闻(News)和物品(Items)之外,还有更多的表:内容(Content)、文章(Post)、表格(Form)等。

以下是我的模型定义:

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public Link Link { get; set; }
}

public class News
{
    public int Id { get; set; }
    public string Header { get; set; }
    public string Content { get; set; }
    public Link Link { get; set; }
}

public class Link
{
    public int Id { get; set; }
    public string Type { get; set; }
    public int RowId  { get; set; }
    public string Url { get; set; }
}

表格Links描述了每个新闻和每个项目的URL。这意味着Links有4列:

  1. Id
  2. Type - 新闻或项目
  3. RowId - 包含项目或新闻的ID(取决于类型)
  4. URL

如何设置关系?请记住,我们需要通过Links表中的URL解析实体。


5
下次请使用更具描述性的标题,并使用适当的标签。[tag:entity-framework]用于旧版EntityFramework(1到6.x)。[tag:entity-framework-core]用于全新、从头开始重写的EF Core。最后,提问此类问题之前,最好先查看文档 https://learn.microsoft.com/en-us/ef/core/modeling/relationships ,而不是等待答案;) - Tseng
EF Core。主要问题是现有数据库不希望修改DB,因为有很多数据和许多具有这些链接(内容、目录等)的实体。 - Alex
4
你所描述的是一种无法使用外键约束描述的数据库模型,因此无法在任何EF版本(包括Core)中进行映射。 - Ivan Stoev
3
这里涉及到了多态关联。如果您想将其转换为带有FK约束的模型,则必须更改数据库架构。 - Gert Arnold
Ivan Stoev,Gert Arnold,感谢您的解释。 - Alex
您可以进一步规范模式并添加两个新表 Link_New:{LinkId, NewId} Link_Item: {LinkId, ItemId}从链接表中删除RowId和Type,告诉它是Item还是News。 - Murtaza Tahir Ali
5个回答

1
Dapper. 只是 Dapper,允许编写自定义查询。

0

更新


我再次阅读了你的问题,说实话,你不需要为链接创建另一个表,只需向新闻、项目等添加一列即可解决问题。

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string Url { get; set; }
}

public class News
{
    public int Id { get; set; }
    public string Header { get; set; }
    public string Content { get; set; }
    public string Url { get; set; }
}

好的想法,适用于新闻和项目。但不会修改链接表并添加列,因为除了新闻和项目之外,还有其他实体,如内容等。这将导致很多空值。这就是为什么这里有“RowId”和“Type”的原因。我能使用类似“HasDiscriminator”或其他技巧吗? - Alex
那么如何构建网站地图呢?对每个表进行foreach并不是一个好主意。顺便说一下,我们有一个描述树形菜单的Menu表。 - Alex
你想为一条记录生成一个链接,最好将其放在同一张表中。另外,对于网站地图,你可以添加一个名为“排序”的列,并以此方式进行管理。 - Masoud Andalibi
这里有一个问题需要找到所需的URL。在请求中,您有URL并需要找出它是什么:项目,新闻,内容,目录或某种形式。这就是为什么我们只有一个链接表的原因。因此,我们无法将URL添加到每个表中。 - Alex

0

我认为你可以从链接表中删除rowid,并在其他两个表中添加一个外键列,引用链接表中的id列。

现在,有了URL,你有了类型和ID,你可以从相应的表中查询内容。


0
我会将Link更改为使用可空的int,并将这些表的外键分开:
public class Link
{
    public int Id { get; set; }
    public string Type { get; set; }
    public int? NewsId  { get; set; }
    public int? ItemId  { get; set; }
    public string Url { get; set; }
}

不行,因为这里除了新闻和物品之外还有很多实体。 - Alex

0
为了拥有NewRow属性,并满足其他两个表的约束条件,您可以这样实现:
public int RowId { 
    public get {
        return this.Type.equals("news") ? NewsId.Value : ItemId.Value;
    };   
    private set {
        if(this.Type.equals("news")){
          NewsId = value;
        }
        else{
          ItemId = value;
        }
    }
}

然后在ContextDB上将此属性设置为未映射。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接