【发布时间】:2022-01-05 08:32:02
【问题描述】:
我有一个带有 EFCore 6.0.1 的新 VS2022 解决方案,网址为:https://github.com/RobBowman/BillByTime
我创建了一个数据库上下文来表示以下内容:
我使用了 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 = "p.arndel@brc.com",
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 = "rob@biztalkers.com",
ClientOrgs = new List<ClientOrg> { clientOrg }
};
var worker = new Worker
{
FirstName = "Fabio",
LastName = "Capello",
Email = "f.cap@ital.com",
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 ()
谁能告诉我为什么它试图在“租户”表中创建多条记录?
【问题讨论】:
-
错误信息是否真的是
The duplicate key value is ()?看起来名称也是空白/空... -
@MartinSmith 是的,似乎它试图在租户表中插入一行,其中 Name 列的值为空
-
你应该在单元测试中播种你的数据吗?数据是否应该在您的第一次 EF 迁移中播种,然后再也不会?否则你只能运行一次这个单元测试,除非你说,你清除所有数据
-
虽然它使用了 xunit,但它不是一个单元测试并且永远不会从 CI 管道运行。这只是检查我是否已设置数据库上下文以使用我所追求的数据库架构的便捷方法。
-
当您清除数据以重新启动时,您是否将其全部删除并重新创建?还是只是手动删除?
标签: c# .net sql-server entity-framework entity-framework-core