我有一個帶有 EFCore 6.0.1 的新 VS2022 解決方案,可在以下
我使用了 VS2022 中的 EFCore Power Tools,并將它創建的圖表與我的預期架構進行了比較——它們匹配!
這是資料庫背景關系 C#:
public class BillByTimeContext : DbContext
{
public BillByTimeContext(DbContextOptions<BillByTimeContext> options) : base(options)
{
RelationalDatabaseCreator databaseCreator =
(RelationalDatabaseCreator)this.Database.GetService<IDatabaseCreator>();
databaseCreator.EnsureCreated();
}
public DbSet<ClientOrg>? ClientOrg { get; set; }
public DbSet<Contract>? Contract { get; set; }
public DbSet<PurchaseOrder>? PurchaseOrder { get; set; }
public DbSet<Tenant> Tenant { get; set; }
public DbSet<TenantManager>? TenantManager { get; set; }
public DbSet<Timesheet>? Timesheet { get; set; }
public DbSet<TimesheetHistory>? TimesheetHistory { get; set; }
public DbSet<Worker>? Worker { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Tenant>()
.HasIndex(x => x.Name)
.IsUnique();
modelBuilder.Entity<TenantManager>()
.HasIndex(x => x.Email)
.IsUnique();
modelBuilder.Entity<Worker>()
.HasMany(p => p.Contracts)
.WithOne(t => t.Worker)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<Timesheet>()
.HasMany(p => p.TimesheetHistories)
.WithOne(t => t.Timesheet)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<Worker>()
.HasMany(p => p.TimesheetHistories)
.WithOne(t => t.Worker)
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<Contract>()
.Property(x => x.UnitCharge)
.HasPrecision(10, 2);
modelBuilder.Entity<PurchaseOrder>()
.Property(x => x.Amount)
.HasPrecision(10, 2);
modelBuilder.Entity<Timesheet>()
.Property(x => x.Monday)
.HasPrecision(10, 2);
modelBuilder.Entity<Timesheet>()
.Property(x => x.Tuesday)
.HasPrecision(10, 2);
modelBuilder.Entity<Timesheet>()
.Property(x => x.Wednesday)
.HasPrecision(10, 2);
modelBuilder.Entity<Timesheet>()
.Property(x => x.Thursday)
.HasPrecision(10, 2);
modelBuilder.Entity<Timesheet>()
.Property(x => x.Friday)
.HasPrecision(10, 2);
modelBuilder.Entity<Timesheet>()
.Property(x => x.Saturday)
.HasPrecision(10, 2);
modelBuilder.Entity<Timesheet>()
.Property(x => x.Sunday)
.HasPrecision(10, 2);
}
}
我有一個呼叫以下SeedData方法的xunit測驗:
public static void SeedData(BillByTimeContext context)
{
context.Database.EnsureCreated();
var timesheetHistory = new TimesheetHistory
{
Timestamp = new DateTime(2022, 1, 7, 14, 30, 0),
StatusId = TimesheetStatus.PendingApproval
};
var timesheet = new Timesheet
{
Monday = 1,
Tuesday = .5M,
Wednesday = 1,
Thursday = 0,
Friday = 1,
WeekCommencingMonday = new DateTime(2022, 01, 03),
TimesheetHistories = new List<TimesheetHistory> { timesheetHistory },
};
var purchaseOrder = new PurchaseOrder
{
DateIssued = DateTime.Now,
Amount = 5462.5M,
Timesheets = new List<Timesheet> { timesheet }
};
var clientManager = new ClientManager
{
FirstName = "Paul",
LastName = "Arndel",
Email = "[email protected]",
SmsNumber = "867428764",
TimesheetHistories = new List<TimesheetHistory> { timesheetHistory }
};
var contract = new Contract
{
UnitId = ContractUnits.Days,
UnitCharge = 550,
Timesheets = new List<Timesheet> { timesheet }
};
var clientOrg = new ClientOrg
{
Name = "BRC",
PurchaseOrders = new List<PurchaseOrder> { purchaseOrder },
ClientManagers = new List<ClientManager> { clientManager },
Contracts = new List<Contract> { contract },
Timesheets = new List<Timesheet> { timesheet }
};
var tenantManager = new TenantManager
{
FirstName = "Rob",
LastName = "Bowman",
Email = "[email protected]",
ClientOrgs = new List<ClientOrg> { clientOrg }
};
var worker = new Worker
{
FirstName = "Fabio",
LastName = "Capello",
Email = "[email protected]",
Contracts = new List<Contract> { contract },
TimesheetHistories= new List<TimesheetHistory> { timesheetHistory }
};
var tenant = context.Tenant.FirstOrDefault(x => x.Name == "BizTalkers");
if (tenant == null)
{
context.Tenant.Add(new Tenant
{
Name = "BizTalkers",
TenantManagers = new List<TenantManager> { tenantManager },
Workers = new List<Worker> { worker }
}); ;
}
context.SaveChanges();
如果我清除資料庫中的所有資料并運行測驗,則會出現以下錯誤:
---- Microsoft.Data.SqlClient.SqlException : Cannot insert duplicate key row in object 'dbo.Tenant' with unique index 'IX_Tenant_Name'. The duplicate key value is ()
誰能告訴我為什么它試圖在“租戶”表中創建多個記錄?
uj5u.com熱心網友回復:
哦.. 剛剛注意到你在 github 上鏈接了你的整個專案——這很有用并證實了我的懷疑:
//worker class
public Tenant Tenant { get; set; } = new();
//tenantmanager class
public Tenant Tenant { get; set; } = new();
每次您創建一個新工人時,它都會創建一個新租戶。EF 會將此視為必須保存的物件。您的圖表至少包含 1 個作業人員(1 個租戶名稱為空白)和 1 個租戶經理(1 個租戶名稱為空白),因此看起來像
{Tenant "BizTalkers"} --has-some--> [ {Worker "Fabio"} --has-one--> { Tenant "" } ]
\
`--has-some--> [ {TenantManager "Rob"} --has-one--> { Tenant "" } ]
目前我不知道為什么 EFCPT 會以這種方式生成物體(如果它確實生成了?)——我的不知道。我不確定它是您打開的選項,還是資料庫端某些東西的結果..如果我發現了什么,我會更新答案,但現在我相信你的問題是由這。= new()從這些道具中洗掉,或在初始化程式中將它們設定為 null,或以其他方式構建圖形(將您創建的租戶設定為您創建的 Worker 的租戶,覆寫new() Tenant它擁有的,而不是設定您創建的 Worker成為您創建的租戶的工人之一)
另外,腳注,通常我會說“避免大規模替換子物體的整個串列” - 這些集合通常new在建構式/類道具初始化程式中作為空 HashSets 出于某種原因,您只需添加到它們而不是替換它們。如果您替換它們,更改跟蹤器可能會認為您正在洗掉內容,并且會發生各種瘋狂的事情
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/407994.html
標籤:
