ASP.NET 核心 2:在这种情况下,"many-to-one" 关系背后的代码可能是什么?
ASP.NET Core 2: What could be the code behind a "many-to-one" relationship in this case?
我正在 ASP .NET Core 2 应用程序中准备项目的数据结构 (code-first) , 在 Entity Framework 的帮助下。我没有经验的这种特定关系:用户必须能够通过复选框选择疾病,我们有类似的选择:癌症类型、饮食等。
我有两个以上像图上的table,会从UserKitProperties table中引用。这个 table 应该像连接器 table 一样工作,将用户实体与其他实体连接起来。
userid1 | cancertypeid1
userid2 | dietaryid1
userid1 | cancertypeid2
userid3 | dietaryid1
这应该如何在代码中指定,以支持这种关系?我正在考虑做一个基础 class 并可能参考那个 id。这是连接器 class..
public class PatientProperties : EntityModel
{
[Key]
public long ID { get; set; }
public long PatientID { get; set; }
[ForeignKey("PatientID")]
public Patient Patients { get; set; }
// this should be used for cancer type, dietary, etc..
public long PropertyID { get; set; }
/* Instead of using two classes' ids, maybe call the base class' id
[ForeignKey("PropertyID")]
public CancerType CancerTypes { get; set; }
[ForeignKey("PropertyID")]
public Dietary Dietaries { get; set; } */
}
提前感谢您的建议! :)
以下应该有效:
public class Property
{
public long PropertyId { get; set; }
}
public class CancerType : Property
{
// Your code
}
public class Dietary : Property
{
// Your code
}
public class PatientProperties : EntityModel
{
[Key]
public long ID { get; set; }
public long PatientID { get; set; }
[ForeignKey("PatientID")]
public Patient Patients { get; set; }
public long PropertyID { get; set; }
[ForeignKey("PropertyID")]
public Property Property { get; set; }
}
但是正如这位 MS doc 提到的,设置这种继承将使用特殊的 Discriminator
base class table 中的列,以表示一行中存储的特定类型。
我个人会使用可空字段来避免增加复杂性。但是,这并不强制要求 PatientProperties
只有一个 属性,这是一个相当大的减号:
public class PatientProperties : EntityModel
{
[Key]
public long ID { get; set; }
public long PatientID { get; set; }
[ForeignKey("PatientID")]
public Patient Patients { get; set; }
public long? CancerTypeID { get; set; }
[ForeignKey("CancerTypeID")]
public CancerType CancerType { get; set; }
public long? DietaryID { get; set; }
[ForeignKey("DietaryID")]
public Dietary Dietary { get; set; }
}
与其首先考虑数据库布局,不如考虑如何在代码中表示这种关系。毕竟,您采用的是代码优先方法。
基本上有两种选择:患者有多个属性,每个 属性 类型一个,或者所有属性只有一个集合:
public class Patient
{
// …
// option 1
public CancerType CancerType { get; set; }
public Dietary Dietary { get; set; }
public OtherProperty OtherProperty { get; set; }
// option 2
public IList<PatientProperty> Properties { get; set; }
}
这两种选择各有优缺点。虽然选项 1 非常明确并且为每种类型强制执行单个值,但它还要求您为每个(患者)属性 设置一个 (class) 属性。所以如果你以后扩展你的模型,你将不得不调整你的患者模型。
方案2的好处是什么都能收。因此,如果您引入新属性,您可以只为您的患者添加属性,而无需稍后修改模型。另外,它也直接支持单一种类的多选。不利的一面是,它不会自行验证任何内容,因此您需要业务逻辑来实际执行您的规则。
转到数据库,对于选项 2,您显然需要 link table,因为现在这是多对多关系。由于您只有 link 到基本类型 PatientProperty
但您实际上想谈论具体类型,因此您将需要某种 鉴别器 。鉴别器基本上只是一种符号,用于在数据库中额外存储对象的种类。
用继承存储数据时,通常做的是“table-per-hierarchy”。这意味着 PatientProperty
基类型层次结构中的所有类型将共享相同的 table。鉴别器列用于指定类型,某些 属性 类型可能具有的其他属性是使用可为空的列实现的。此设置与 Entity Framework 开箱即用,并在 in this chapter in the documentation.
中进行了描述
另一种方法“table-per-type”在 EF Core 中不受支持,因此如果您想遵循该方法,则必须自己实施。但在你的情况下,属性 类型大多非常相似,我实际上会反对这一点并实际上将它们保持在相同的 table.
对于选项 1,只要每种类型的 属性 分配给患者,事情就会简单一些。因为那里没有多对多,所以你实际上不需要 link table。您只需要在患者模型中存储每个 linked 属性 类型的 ID,如上面的 UML 所示。这样做,您还可以将 属性 类型保留为不在数据库中共享单个 table 的单独类型。
我正在 ASP .NET Core 2 应用程序中准备项目的数据结构 (code-first) , 在 Entity Framework 的帮助下。我没有经验的这种特定关系:用户必须能够通过复选框选择疾病,我们有类似的选择:癌症类型、饮食等。
我有两个以上像图上的table,会从UserKitProperties table中引用。这个 table 应该像连接器 table 一样工作,将用户实体与其他实体连接起来。
userid1 | cancertypeid1
userid2 | dietaryid1
userid1 | cancertypeid2
userid3 | dietaryid1
这应该如何在代码中指定,以支持这种关系?我正在考虑做一个基础 class 并可能参考那个 id。这是连接器 class..
public class PatientProperties : EntityModel
{
[Key]
public long ID { get; set; }
public long PatientID { get; set; }
[ForeignKey("PatientID")]
public Patient Patients { get; set; }
// this should be used for cancer type, dietary, etc..
public long PropertyID { get; set; }
/* Instead of using two classes' ids, maybe call the base class' id
[ForeignKey("PropertyID")]
public CancerType CancerTypes { get; set; }
[ForeignKey("PropertyID")]
public Dietary Dietaries { get; set; } */
}
提前感谢您的建议! :)
以下应该有效:
public class Property
{
public long PropertyId { get; set; }
}
public class CancerType : Property
{
// Your code
}
public class Dietary : Property
{
// Your code
}
public class PatientProperties : EntityModel
{
[Key]
public long ID { get; set; }
public long PatientID { get; set; }
[ForeignKey("PatientID")]
public Patient Patients { get; set; }
public long PropertyID { get; set; }
[ForeignKey("PropertyID")]
public Property Property { get; set; }
}
但是正如这位 MS doc 提到的,设置这种继承将使用特殊的 Discriminator base class table 中的列,以表示一行中存储的特定类型。
我个人会使用可空字段来避免增加复杂性。但是,这并不强制要求 PatientProperties
只有一个 属性,这是一个相当大的减号:
public class PatientProperties : EntityModel
{
[Key]
public long ID { get; set; }
public long PatientID { get; set; }
[ForeignKey("PatientID")]
public Patient Patients { get; set; }
public long? CancerTypeID { get; set; }
[ForeignKey("CancerTypeID")]
public CancerType CancerType { get; set; }
public long? DietaryID { get; set; }
[ForeignKey("DietaryID")]
public Dietary Dietary { get; set; }
}
与其首先考虑数据库布局,不如考虑如何在代码中表示这种关系。毕竟,您采用的是代码优先方法。
基本上有两种选择:患者有多个属性,每个 属性 类型一个,或者所有属性只有一个集合:
public class Patient
{
// …
// option 1
public CancerType CancerType { get; set; }
public Dietary Dietary { get; set; }
public OtherProperty OtherProperty { get; set; }
// option 2
public IList<PatientProperty> Properties { get; set; }
}
这两种选择各有优缺点。虽然选项 1 非常明确并且为每种类型强制执行单个值,但它还要求您为每个(患者)属性 设置一个 (class) 属性。所以如果你以后扩展你的模型,你将不得不调整你的患者模型。
方案2的好处是什么都能收。因此,如果您引入新属性,您可以只为您的患者添加属性,而无需稍后修改模型。另外,它也直接支持单一种类的多选。不利的一面是,它不会自行验证任何内容,因此您需要业务逻辑来实际执行您的规则。
转到数据库,对于选项 2,您显然需要 link table,因为现在这是多对多关系。由于您只有 link 到基本类型 PatientProperty
但您实际上想谈论具体类型,因此您将需要某种 鉴别器 。鉴别器基本上只是一种符号,用于在数据库中额外存储对象的种类。
用继承存储数据时,通常做的是“table-per-hierarchy”。这意味着 PatientProperty
基类型层次结构中的所有类型将共享相同的 table。鉴别器列用于指定类型,某些 属性 类型可能具有的其他属性是使用可为空的列实现的。此设置与 Entity Framework 开箱即用,并在 in this chapter in the documentation.
另一种方法“table-per-type”在 EF Core 中不受支持,因此如果您想遵循该方法,则必须自己实施。但在你的情况下,属性 类型大多非常相似,我实际上会反对这一点并实际上将它们保持在相同的 table.
对于选项 1,只要每种类型的 属性 分配给患者,事情就会简单一些。因为那里没有多对多,所以你实际上不需要 link table。您只需要在患者模型中存储每个 linked 属性 类型的 ID,如上面的 UML 所示。这样做,您还可以将 属性 类型保留为不在数据库中共享单个 table 的单独类型。