簡體   English   中英

實體框架核心一對多關系

[英]Entity Framework core one to many relationship

我正在嘗試建立具有一對多關系的代碼優先數據模型。

有一個UserDTO和RoleDTO模型,其中User包含一對多角色。

RoleDTO的一些簡化代碼是:

internal class RoleDTO
{
    public UserDTO User { get; set; }

    public string Value { get; set; }

    public RoleDTO()
    {

    }
}

和簡化的UserDTO:

internal class UserDTO
{
    public string Email { get; set; }

    public string FullName { get; set; }

    public string UserName { get; set; }

    public virtual ICollection<RoleDTO> Roles { get; set; }

    public UserDTO()
    {

    }
}

最后是從DBContext繼承的類

class StorageContext : DbContext
{
    public DbSet<UserDTO> Users { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"My_Connection_String");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<UserDTO>().HasKey(entity => entity.Email);
        modelBuilder.Entity<UserDTO>().HasMany(entity => entity.Roles);

        modelBuilder.Entity<RoleDTO>().HasOne<UserDTO>().WithMany(x => x.Roles);
        modelBuilder.Entity<RoleDTO>().HasKey(x => x.Value);
    }
}

當我運行添加遷移時,我沒有數據庫或遷移文件夾(即使我仍然在擁有一些列之后運行了該文件夾),Role表也會用指向用戶電子郵件地址的額外列創建。

我只希望角色表中有兩列,一列是用戶的電子郵件地址,是用戶電子郵件PK的FK,另一列是與外鍵組合的字符串值,在用戶表中構成復合主鍵。 下圖:

*******************************
* Role                        *
*******************************
* User_Email - string/varchar *
* Value - string /varchar     *
*******************************
FK - User_Email to User table Email column
PK - User_Email, Value compound primary key

有誰知道如何使用流暢的API或數據注釋來實現這一目標?

謝謝!

我不確定您要達到的目的,但是在ORM中使用復合鍵可能會很復雜,而且可能是不可預測的。 因此,除非您有充分的理由,否則我建議您不要使用復合鍵。

我建議不要在任何地方將電子郵件地址用作PK。 使用唯一生成的Int32 / Int64甚至Guid作為主鍵(一旦設置了關系,它將作為外鍵反映在您的Roles表中),並在您的電子郵件列(在User表中)上添加一個索引,唯一的約束。 您可以在遷移腳本中添加索引。 至少以這種方式,如果電子郵件地址要更改(如果要更改),則可以保留身份。

我希望這有幫助。

首先,類UserDTO沒有名為User_Email屬性。 您可以使用EF在模型中定義陰影屬性,但考慮到您希望它在模型中,則應在類public string User_Email上定義屬性

使用流利的API在類上定義上述屬性或在模型中定義陰影屬性后,

要定義復合主鍵,您需要使用HasKey流利的API。 您不能使用數據注釋來定義復合主鍵。

要將User_Email, Value定義為復合PK,請在OnModelCreating編寫以下代碼(如果定義了陰影屬性,則可以這樣做)

modelBuilder.Entity<UserDTO>().HasKey(e => new { e.User_Email, e.Value });

要為關系指定外鍵屬性,可以在fk屬性/導航上使用ForeignKeyAttribute ,也可以使用HasForeignKey fluent API。

要設置User_Email是FK到UserDTO表,假設UserDTO UserRoleDTOICollection<RoleDTO> RolesUserDTO是這種關系導航。

使用數據注釋,在User_Email屬性上寫ForeignKey("User")或在任一導航( User / Roles )上寫ForeignKey("User_Email") )。 請記住,如果您具有User_Email作為shadow屬性,則不能使用它。

使用Fluent API,在OnModelCreating編寫以下代碼以完全配置關系

modelBuilder.Entity<RoleDTO>().HasOne(e => e.User).WithMany(e => e.Roles).HasForeignKey(e => e.User_Email);

上面將使用“ UserRoles導航創建一對多關系,該導航使用User_Email作為外鍵屬性。

您的代碼無法正常工作的原因是

  1. 使用HasKey ,您定義了單個屬性PK而不是復合PK。
  2. 您尚未使用HasForeignKey方法指定外鍵屬性,因此EF將為您添加陰影屬性。 此外,在關系配置中,您僅使用了Roles導航。 EF將嘗試使用“ User導航”創建另一個關系,從而在UserDTORoleDTO之間有效地建立2個關系。 這就是您獲得額外的列的原因,因為EF按照慣例創建了陰影屬性以用作外鍵屬性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM