我對 EF Core 6.0 很陌生。我們目前有一個要升級的專案,我們無法更改實際表(由另一個程式使用),因此我們使用 Database fisrt approch。所以我需要為用戶添加一些權限(資料庫是法語)我們目前有一個 UsagerEW 表(用戶表),我們為 Many2Many 添加了一個權限表和一個聯合表 PermissionUsagerEW。執行 Scaffold-dbContect 后,結果如下:
UsagerEW(主鍵是 Code_Int)
public partial class UsagerEW
{
public UsagerEW()
{
PermissionUsagerEW = new HashSet<PermissionUsagerEW>();
RefreshToken = new HashSet<RefreshToken>();
}
public string Code { get; set; }
public string Nom { get; set; }
public string Email { get; set; }
public string ModeLogin { get; set; }
public string PasswordTemp { get; set; }
public DateTime? PasswordTempExp { get; set; }
public int code_int { get; set; }
public virtual ICollection<PermissionUsagerEW> PermissionUsagerEW { get; set; }
}
Pemrssion 和 PermissionUsagerEW
public partial class Permission
{
public Permission()
{
PermissionUsagerEW = new HashSet<PermissionUsagerEW>();
}
public int id { get; set; }
public string code { get; set; }
public string description { get; set; }
public int? moduleId { get; set; }
public virtual Module module { get; set; }
public virtual ICollection<PermissionUsagerEW> PermissionUsagerEW { get; set; }
}
public partial class PermissionUsagerEW
{
public int id { get; set; }
public int permissionId { get; set; }
public int usagerCodeInt { get; set; }
public virtual Permission permission { get; set; }
public virtual UsagerEW usagerCodeIntNavigation { get; set; }
}
編譯后我可以從 UsagerEW 中“使用包含導航”并獲取特定 UsagerEW 的 PermissionUsagerEW 串列。
現在就像我在應該支持 Many2Many 的 EF Core 6.0 中一樣,我在 Permnission 類中添加了這個導航屬性
public virtual ICollection<UsagerEW> UsagerEW { get; set; }
這在 UsagerEW 類中:
public virtual ICollection<Permission> Permission { get; set; }
但是我遇到了執行錯誤,或者我只是嘗試加載一些用戶 wintout 任何包括:
UsagerEW user = _EWContext.UsagerEW.Where(u=>u.Code == usagerId).SingleOrDefault();
System.InvalidOperationException: 'Cannot use table 'PermissionUsagerEW' for entity type 'PermissionUsagerEW (Dictionary<string, object>)' since it is being used for entity type 'PermissionUsagerEW' and potentially other entity types, but there is no linking relationship. Add a foreign key to 'PermissionUsagerEW (Dictionary<string, object>)' on the primary key properties and pointing to the primary key on another entity type mapped to 'PermissionUsagerEW'.'
The FK are detect by the scaffold:
modelBuilder.Entity<PermissionUsagerEW>(entity =>
{
entity.HasOne(d => d.permission)
.WithMany(p => p.PermissionUsagerEW)
.HasForeignKey(d => d.permissionId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_PermissionUsager_Permission");
entity.HasOne(d => d.usagerCodeIntNavigation)
.WithMany(p => p.PermissionUsagerEW)
.HasForeignKey(d => d.usagerCodeInt)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_PermissionUsager_Usager");
});
Any idea?
---EDIT 1 I change your code to reflect the scaffolded PermissionUsagerEW table:
//--UsagewrEW
modelBuilder.Entity<UsagerEW>()
.HasKey(u => u.code_int);
modelBuilder.Entity<UsagerEW>()
.HasMany(u => u.Permissions)
.WithMany(p => p.Users)
.UsingEntity<PermissionUsagerEW>(
p => p.HasOne(e => e.permission)
.WithMany()
.HasForeignKey(e => e.permissionId),
p => p.HasOne(p => p.usagerCodeIntNavigation)
.WithMany()
.HasForeignKey(e => e.usagerCodeInt)
);
modelBuilder.Entity<PermissionUsagerEW>()
.HasOne(p => p.usagerCodeIntNavigation)
.WithMany()
.HasForeignKey(p => p.usagerCodeInt);
When testing with UsagerEW user = _EWContext.UsagerEW.Where(u=>u.Code == usagerId).Include(u => u.Permissions).SingleOrDefault();
Now I got this error:
Microsoft.Data.SqlClient.SqlException: '無效的列名'UsagerEWcode_int'。'
我認為 EF 會嘗試自動鏈接某些內容。我的解決方案中沒有任何 UsagerEWcode_int。
EDIT2:有生成的 SQL。奇怪的列名和一些重復......
SELECT [u].[code_int], [u].[Administrateur], [u].[Code], [u].[Email], [u].[EmpContact], [u].[Inactif], [u].[KelvinConfig], [u].[LectureSeule], [u].[ModeLogin], [u].[Nom], [u].[ParamRole], [u].[Password], [u].[PasswordTemp], [u].[PasswordTempExp], [u].[RestreintCommContrat], [u].[RestreintProjet], [u].[Role], [u].[UsagerAD], [u].[doitChangerPW], [u].[estSuperviseur], [u].[idSuperviseur], [u].[infoSession], [u].[paramRole2], [u].[permsGrps], [t].[id], [t].[Permissionid], [t].[UsagerEWcode_int], [t].[permissionId0], [t].[usagerCodeInt], [t].[id0], [t].[code], [t].[description], [t].[moduleId]
FROM [UsagerEW] AS [u]
LEFT JOIN (
SELECT [p].[id], [p].[Permissionid], [p].[UsagerEWcode_int], [p].[permissionId] AS [permissionId0], [p].[usagerCodeInt], [p0].[id] AS [id0], [p0].[code], [p0].[description], [p0].[moduleId]
FROM [PermissionUsagerEW] AS [p]
INNER JOIN [Permission] AS [p0] ON [p].[permissionId] = [p0].[id]
) AS [t] ON [u].[code_int] = [t].[usagerCodeInt]
WHERE [u].[Code] = @__usagerId_0
ORDER BY [u].[code_int], [t].[id]
uj5u.com熱心網友回復:
您可以配置與現有資料庫的直接多對多關系,并且您可以在模型中包含鏈接物體或排除它。檔案中有幾個示例。并且您可以將外鍵屬性保留在模型中,或者您可以將它們替換為陰影屬性。但是 Scaffolding 代碼不會為您做任何這些。它為資料庫模式創建最簡單的正確模型。
此外,您通常應該重命名物體和屬性以符合 .NET 編碼約定。
無論如何,這樣的事情應該有效:
public partial class UsagerEW
{
public string Code { get; set; }
public string Nom { get; set; }
public string Email { get; set; }
public string ModeLogin { get; set; }
public string PasswordTemp { get; set; }
public DateTime? PasswordTempExp { get; set; }
public int code_int { get; set; }
public virtual ICollection<Permission> Permissions { get; } = new HashSet<Permission>();
}
public partial class Permission
{
public int Id { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public int? ModuleId { get; set; }
//public virtual Module module { get; set; }
public virtual ICollection<UsagerEW> Users { get; } = new HashSet<UsagerEW>();
}
public partial class PermissionUsagerEW
{
public int Id { get; set; }
public int PermissionId { get; set; }
public int UsagerCodeInt { get; set; }
public virtual Permission Permission { get; set; }
public virtual UsagerEW User { get; set; }
}
public class Db : DbContext
{
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<UsagerEW>()
.HasKey(u => u.code_int);
builder.Entity<UsagerEW>()
.HasMany(u => u.Permissions)
.WithMany(p => p.Users)
.UsingEntity<PermissionUsagerEW>(
p => p.HasOne(e => e.Permission)
.WithMany()
.HasForeignKey(e => e.PermissionId),
p => p.HasOne(p => p.User)
.WithMany()
.HasForeignKey( e => e.UsagerCodeInt)
);
builder.Entity<PermissionUsagerEW>()
.HasOne(p => p.User)
.WithMany()
.HasForeignKey(p => p.UsagerCodeInt);
foreach (var prop in builder.Model.GetEntityTypes().SelectMany(e => e.GetProperties()))
{
prop.SetColumnName(char.ToLower(prop.Name[0]) prop.Name.Substring(1));
}
base.OnModelCreating(builder);
}
但是,當您在資料庫優先的作業流中作業時,深度自定義 EF 模型有一個缺點:您失去了從資料庫重新生成 EF 模型的能力。
因此,您可以使用“漂亮”的自定義 EF 模型,或“普通”的腳手架模型。如果您自定義模型,您將無法再重新生成它,并且需要手動更改它以匹配未來的資料庫更改。
不過,您可以應用一些自定義,例如示例中基于約定的屬性到列和物體到表的映射。但是將生成的“間接多對多”更改為“直接多對多”將阻止您通過腳手架重新生成 EF 模型。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/381546.html
標籤:实体框架
下一篇:如何在EFCORE中創建祖父外鍵
