代码 前两个对象具有其他对象

本文关键字:对象 其他 两个 代码 | 更新日期: 2023-09-27 18:34:49

首先使用实体框架代码,我有这个:

public class Person {
    public int PersonId {get;set;}
    public string FirstName {get;set;}
    public string LastName {get;set;}
    public virtual List<Note> Notes {get;set;}
}
public class Product {
    public int ProductId {get;set;}
    public string Name {get;set;}
    public virtual List<Note> Notes {get;set;}
}
public class Note {
    public int NoteId {get;set;}
    public string Body {get;set;}
    public virtual User Author {get;set;}
    // what should be here ?
}

我如何知道笔记是来自个人还是产品?我应该为此需要不同的类(PersonNote,ProductNote(吗?我可以使用接口方法吗?喜欢不可思议 ?

我不确定对数据库或类进行建模的最佳策略是什么。任何建议不胜感激。

谢谢

编辑(基于答案(

建议的答案意味着对于每个有注释的实体,表格将有一个我不太喜欢的新列。有没有办法使用鉴别器?我不喜欢每次新实体可以有注释时修改表的想法,如果我有 10 个支持注释的实体,则最终可能会得到 10 FK(9 总是空(。

理想情况下,我希望拥有类似接口(或其他任何东西(的东西,这样我就可以在代码中拥有产品:不可操作,这意味着可以使用此 id 创建注释。也许带有鉴别器列。这可能吗?

很抱歉第一次不清楚。

在现实生活中,我有这样的:产品、人员、采购订单、销售、付款、付款订单以及我需要实现注释的更多实体。

编辑 2 :

这个数据库结构怎么样:

TABLE: Note
int PK NoteId
int FK NoteDataId
string Body
TABLE: Person
int PK PersonId 
int FK NoteDataId
TABLE: Product
int PK ProductId
int FK NoteDataId
TABLE: NoteData
int PK NoteDataId

使用此数据结构,所有想要实现 Notes 的实体我只需添加一个导航属性 NoteDataId,在创建注释时,我只提供 NoteDataId 值。我认为EF将负责创建NoteDataId行(如果它不存在(。

编辑3:

示例数据:

Person:
PersonId 1
Name Bart
NoteDataId 1
PersonId 2
Name Alex
NoteDataId 2
Product:
ProductId 1
Name "Dulce de Leche"
NoteDataId 3
NoteData:
NoteDataId 1
NoteDataId 2
NoteDataId 3
Note:
NoteId 1
NoteDataId 1
Body "first note"
NoteId 2
NoteDataId 1
Body "second note of Bart"
NoteId 3
NoteDataId 2
Body "first note of Alex"
NoteId 4
NoteDataId 3
Body "Note about Dulce de Leche"

如何获得某人的笔记?

SELECT * FROM Note
JOIN NoteData USING (NoteDataId)
JOIN Person USING (NoteDataId)
WHERE PersonId = 1

向后?

SELECT * FROM Note
JOIN NoteData USING (NoteDataId)
LEFT JOIN Person USING (NoteDataId) 'can be null, only one type exists'
LEFT JOIN Product using (NoteDataId) 'can be null, only one type exists'
WHERE NoteId = 2

代码 前两个对象具有其他对象

创建可为空的外键:

public class Note {
    public int NoteId {get;set;}
    public string Body {get;set;}
    public virtual User Author {get;set;}
    public int? PersonId { get; set; }
    public virtual Person Person { get; set; }
    public int? ProductId { get; set; }
    public virtual Product Product { get; set; }
}

您必须将属性映射为可选属性。

Note的配置:

Property(n => n.PersonId).IsOptional();
Property(n => n.ProductId).IsOptional();

PersonProduct的配置:

Property(p => p.Note).IsOptional();

<小时 />更新

还可以使用按层次结构表的解决方案。

保留Note相同(不妨将其抽象(并创建派生类型。例如PersonNote

public clas PersonNote : Note 
{   
    public int PersonId { get; set; }
    public virtual Person Person { get; set; }
}

Person获取导航属性的位置:

public virtual PersonNote Note { get; set; }

ProductNote

public clas ProductNote : Note 
{   
    public int ProductId { get; set; }
    public virtual Product Product { get; set; }
}

Product获取导航属性的位置:

public virtual ProductNote Note { get; set; }

实体框架将创建一个包含派生类型的所有属性和一个discriminator列的Note表。但这会导致你的代码中有很多类,但在我看来这不是一件坏事。

<小时 />

更新 2

如果

不需要,还可以将导航属性从Note放到ProductPerson。这将使您的代码更简单。您可以保持原样Note,并将导航和外键属性添加到其他实体:

public class Person
{
    // properties..
    public int NoteId { get; set; }
    public virtual Note Note { get; set; }
}

编辑:考虑一切。这并不能解决第一个问题,我们只添加了另一个表。为什么不添加一个映射到枚举的注释类型列。


根据你上次的编辑,这就是我做代码的方式

public class Person {
    public int PersonId {get;set;}
    public string FirstName {get;set;}
    public string LastName {get;set;}
    public int NoteData NoteDataId{get;set;}
    [ForeignKey("NoteDataId")]
    public virtual NoteData NoteData{get;set;}
}
public class Product {
    public int ProductId {get;set;}
    public string Name {get;set;}
    public int NoteData NoteDataId{get;set;}
    [ForeignKey("NoteDataId")]
    public virtual NoteData NoteData{get;set;}
}
public class NoteData {
    public int NoteDataID {get;set;}
    public virtual List<Note> Notes {get;set;}
}    
public class Note {
    public int NoteId {get;set;}
    public string Body {get;set;}
    public int NoteData NoteDataId{get;set;}
    [ForeignKey("NoteDataId")]
    public virtual NoteData NoteData{get;set;}
}

我不确定它如何适用于 EF,但在我们的模型中,我们使用返回对象的通用"Parent"属性。 仅当只有一个对象拥有注释,而引用注释的对象不多时,此操作才有效。

public virtual object Parent { get; set; }

但是,我认为 EF 不会自动为您填充它......