【发布时间】:2021-09-21 22:41:49
【问题描述】:
我正在尝试使用 SQL Server 在 ef-core 中对付款进行建模。支付有一个从方和一个到方,在这种情况下说每个用户或参与者。我有一个与 FromActor 和 ToActor 有关系的事务类。生成的迁移在数据库中更新失败,说明可能有多个级联路径。我已经读到我需要在 db 上下文中覆盖 OnModelCreating 方法中的默认级联,但我不确定如何。对 EF 和迁移相当陌生,我只是关注 https://docs.microsoft.com/en-us/ef/core/get-started/overview/first-app?tabs=visual-studio。
public class Actor
{
public int ActorId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Transaction> Transactions = new List<Transaction>();
}
public class Transaction
{
public int TransactionId { get; set; }
public DateTime TimestampUtc { get; set; }
public decimal Amount { get; set; }
public int FromActorId { get; set; }
public Actor FromActor { get; set; }
public int ToActorId { get; set; }
public Actor ToActor { get; set; }
}
在表“事务”上引入 FOREIGN KEY 约束“FK_Transactions_Actors_ToActorId”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。
您能告诉我如何在 db 上下文中进行这项工作吗?还是我需要对我的域进行不同的建模?
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
??
}
更新:根据我在这里收到的所有 cmets 是我最终的工作解决方案 -
public class Actor
{
public int ActorId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual List<Transaction> FromTransactions { get; set; }
public virtual List<Transaction> ToTransactions { get; set; }
}
public class Transaction
{
public int TransactionId { get; set; }
public DateTime TimestampUtc { get; set; }
public double Amount { get; set; }
public int FromActorId { get; set; }
public virtual Actor FromActor { get; set; }
public int ToActorId { get; set; }
public virtual Actor ToActor { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Transaction>(entity =>
{
entity.HasOne(t => t.FromActor)
.WithMany(a => a.FromTransactions)
.HasForeignKey(t => t.FromActorId)
.OnDelete(DeleteBehavior.NoAction)
.HasConstraintName("FK_Transaction_Id_From_Actor");
entity.HasOne(t => t.ToActor)
.WithMany(a => a.ToTransactions)
.HasForeignKey(t => t.ToActorId)
.OnDelete(DeleteBehavior.NoAction)
.HasConstraintName("FK_Transaction_Id_To_Actor");
});
Seed(modelBuilder);
}
private void Seed(ModelBuilder modelBuilder)
{
using (var reader = new StreamReader("Data/Actors.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
var actors = csv.GetRecords<Actor>();
modelBuilder.Entity<Actor>().HasData(actors.ToArray());
}
}
protected async Task<Transaction> SaveTransactionAsync()
{
using (var context = contextFactory.CreateDbContext())
{
var transaction = new Transaction()
{
TimestampUtc = DateTime.UtcNow,
Amount = 20.45, // hardcoded for illustration
FromActorId = 1, // hardcoded for illustration. Using id from actor seed file.
ToActorId = 2, // hardcoded for illustration. Using id from actor seed file.
};
context.Add(transaction);
await context.SaveChangesAsync();
await context.Entry(transaction).Reference(t => t.FromActor).LoadAsync();
await context.Entry(transaction).Reference(t => t.ToActor).LoadAsync();
logger.LogDebug("Saved transaction to database.");
return transaction;
}
}
除了禁用删除级联之外,主要的教训是我必须为 Actor 引入 2 个集合(从和到)。而且我无法在保存期间设置事务的 FromActor 和 ToActor 属性;只设置ID。设置对象会在事务保存期间尝试插入到 Actors 表中。不直观。
感谢您的帮助。
【问题讨论】:
标签: .net entity-framework-core