實體框架核心一對多關係

c# entity-framework-core one-to-many

我正在嘗試構建具有一對多關係的代碼第一個數據模型。

有一個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或數據註釋來實現這一目標?

謝謝!

一般承認的答案

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

一旦在類上定義了屬性,或者使用fluent API在模型中定義了shadow屬性,

要定義復合主鍵,您需要使用HasKey fluent API。您無法使用數據註釋來定義復合主鍵。

要定義User_Email, Value作為複合PK,在OnModelCreating編寫以下代碼(如果你那樣定義了shadow屬性)

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

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

要將User_Email設置為FK到UserDTO表,假設UserDTO UserRoleDTO ICollection<RoleDTO> Roles UserDTO中的ICollection<RoleDTO> Roles是此關係的導航。

使用數據註釋,在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創建的shadow屬性按慣例用作外鍵屬性。

熱門答案

我不確定你要用它來實現什麼,但在ORM中使用複合鍵可能很複雜,而且這個區域可能無法預測。所以除非你有充分的理由,否則我會建議反對複合鍵。

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

我希望這有幫助。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因