简体   繁体   English

ASP.NET Core 2:在这种情况下,“多对一”关系背后的代码是什么?

[英]ASP.NET Core 2: What could be the code behind a “many-to-one” relationship in this case?

I'm preparing a project's data structure ( code-first ) in an ASP .NET Core 2 application, with the help of Entity Framework . 我在实体框架的帮助下,在ASP .NET Core 2应用程序中准备项目的数据结构( 代码优先 )。 This specific relationship I have no experience with: the user has to be able to choose diseases with checkboxes, and we have similar choices: cancer type, dietary, etc.. 这种特殊的关系,我没有经验:用户必须能够选择具有复选框的疾病,我们有类似的选择:癌症类型,饮食等。

I have more than two tables like the ones on the picture, which will be referred from the UserKitProperties table. 我有两个以上的表,如图片中的表,将从UserKitProperties表中引用。 This table should work like a connector table, connects the user entity with other entities. 此表应该像连接器表一样工作,将用户实体与其他实体连接起来。

userid1 | cancertypeid1
userid2 | dietaryid1
userid1 | cancertypeid2
userid3 | dietaryid1

在此输入图像描述

How should this be specified in the code, to support this relationship? 如何在代码中指定,以支持这种关系? I was thinking on doing a base class and maybe refer to that id. 我正在考虑做一个基类,也许可以参考那个id。 And this is the connector 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; } */
    }

Thank you in advance for your suggestions! 提前感谢您的建议! :) :)

The following should work: 以下应该有效:

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; }
}

But as this MS doc mentions, setting up such inheritence will use a special Discriminator column in the base class table, to represent what specific type is stored in a row. 但是正如MS 文档所提到的,设置这样的继承将在基类表中使用特殊的Discriminator列来表示存储在一行中的特定类型。

I personally would resort to having nullable fields instead in order to not add more complexity. 我个人会求助于可空字段,以免增加复杂性。 This doesn't enforce, however, that PatientProperties only has one property, which is a considerable minus: 但是,这并不强制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; }
}

Instead of thinking about the database layout first, you should think about how you would represent this relationship in code. 您应该考虑如何在代码中表示这种关系,而不是首先考虑数据库布局。 After all, you are doing a code-first approach. 毕竟,您正在采用代码优先的方法。

There are basically two choices you could choose: Either the patient has multiple properties, one for each property type, or there is just a single collection for all properties: 您可以选择两种选择:患者有多个属性,每种属性类型一个,或者所有属性只有一个集合:

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; }
}

Both of these options have their advantages and disadvantages. 这两种选择都有其优点和缺点。 While option 1 is very explicit and enforces a single value for every type, it also requires you to have a (class) property for every (patient) property. 虽然选项1非常明确并且为每种类型强制执行单个值,但它还要求您为每个(患者)属性提供(类)属性。 So if you extend your model later, you will have to adjust your patient model. 因此,如果您稍后扩展模型,则必须调整患者模型。

选项1

Option 2 has the benefit that it can just collect everything. 选项2的好处是它可以收集所有东西。 So you can just add properties to your patient without having to modify the model later if you introduce new properties. 因此,您可以向患者添加属性,而无需在以后引入新属性时修改模型。 In addition, it would also directly support multiple selections for a single kind. 此外,它还可以直接支持单一种类的多种选择。 On the downside, it does not verify anything on its own, so you need business logic to actually enforce your rules. 在缺点方面,它不会自行验证任何内容,因此您需要业务逻辑来实际执行您的规则。

选项2


Moving onto the database, for option 2 you obviously need a link table since that is a many-to-many relationship now. 转到数据库,对于选项2,你显然需要一个链接表,因为这是一个多对多的关系。 Since you only have a link to the base type PatientProperty but you actually want to talk about the concrete type, you will need some kind of discriminator . 由于您只有一个基本类型PatientProperty的链接,但您实际上想要讨论具体类型,您将需要某种鉴别器 Discriminators are basically just a notation to additionally store the kind of object in the database. 鉴别器基本上只是另外在数据库中存储对象类型的表示法。

When storing data with inheritance, what is commonly done is “table-per-hierarchy”. 使用继承存储数据时,通常所做的是“每层次表”。 That means that all types within the hierarchy of the PatientProperty base type will share the same table. 这意味着PatientProperty基本类型的层次结构中的PatientProperty类型将共享同一个表。 A discriminator column is used to specify the type, and additional properties that some property types may have are implemented with nullable columns. 鉴别器列用于指定类型,并且某些属性类型可能具有的其他属性使用可空列实现。 This setup works out of the box with Entity Framework and is described in this chapter in the documentation . 此设置与Entity Framework一起开箱即用,并在本章的文档中进行了描述

The other approach, “table-per-type” is not supported in EF Core, so if you wanted to follow that, you would have to implement it yourself. EF Core不支持另一种方法“每个类型的表”,所以如果你想遵循它,你必须自己实现它。 But in your case, where the property types are mostly very similar, I would actually argue against that and actually keep them in the same table. 但在你的情况下,属性类型大多非常相似,我实际上会反对,并实际上将它们保存在同一个表中。

For option 1, as long as you only have a single property of each kind assigned to the patient, things are a bit simpler. 对于选项1,只要您只为患者分配了每种类型的单一属性,事情就会简单一些。 Since you don't have many-to-many there, you don't actually need a link table. 由于那里没有多对多,因此实际上并不需要链接表。 You just need to store the id for each linked property type in the patient model, as shown in the above UML. 您只需要在患者模型中存储每个链接属性类型的id,如上面的UML所示。 Doing that, you can also keep the property types as separate types that do not share a single table in the database. 这样做,您还可以将属性类型保留为不共享数据库中的单个表的单独类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 多对一关系 - Many-to-one relationship 在 .Net 核心中映射多对一关系 - Mapping many-to-one relations in .Net core ASP.NET Core 3.1 和 Entity Framework Core:一对多的关系 - ASP.NET Core 3.1 and Entity Framework Core : one-to-many relationship 更新 asp.net 核心 mvc 中的多对多关系 - Updating a many-to-many relationship in asp.net core mvc ASP.NET CORE 3.1 中通过存储库模式的多对多关系 - Many to Many relationship in ASP.NET CORE 3.1 by repository pattern EF代码首先与ASP.NET身份表建立多对多关系 - EF Code First Many-to-Many Relationship with ASP.NET Identity Table at one Side 如何在 Asp.NET Core 中的个人用户帐户之间添加一对多关系 - How to add one to many relationship between Individual user accounts in Asp.NET Core 如何在一对多关系类中获取 asp.net 核心实体中的特定字段 - how to get specific fields in asp.net core entity in one to many relationship classes asp.Net Core 一对多关系 UPDATE 语句与 FOREIGN KEY 约束冲突 - asp.Net Core one-to-many relationship UPDATE statement conflicted with the FOREIGN KEY constraint ASP.NET Core中如何将一对多的关系数据添加到数据库中? - How to add one-to-many relationship data to the database in ASP.NET Core?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM