C# EF6外键上的唯一约束
我有以下场景:C# EF6外键上的唯一约束,c#,entity-framework-6,C#,Entity Framework 6,我有以下场景: public class Book { [Key] public string Isbn { get; set; } public string Title { get; set; } public int Stock { get; set; } public Author Author { get; set; } } public class Author { public int Au
public class Book {
[Key]
public string Isbn { get; set; }
public string Title { get; set; }
public int Stock { get; set; }
public Author Author { get; set; }
}
public class Author {
public int AuthorId { get; set; }
[Index(IsUnique = true)]
[StringLength(50)]
public string Name { get; set; }
public ICollection<Book> Books { get; set; }
}
我看到的是,有时FirstOrDefault返回null,但插入失败,因为违反了作者名称上的唯一索引。是否有一些英孚的诡计可以让这一切以一种简单的方式发生?我想我可以使用存储过程,但如果可能的话,我想在客户端使用它。尝试了各种方法后,我选择了以下方法:
var author = _ctx.Authors.SqlQuery(
"with data as (select @author as [name]) " +
"merge Authors a " +
"using data s on s.[name] = a.[name] " +
"when not matched by target " +
"then insert([name]) values(s.[name]); select * from Authors where [name]=@author", new SqlParameter("author", command.Author)).Single();
var book = new Book
{
Isbn = command.Id,
Title = command.Title,
Stock = command.Count,
Author = author
};
_ctx.Books.Add(book);
await _ctx.SaveChangesAsync();
虽然不美观,但这确实防止了作者检查和使用db本机特性插入之间的竞争条件。ORMs和泄漏的抽象,呃:)
我想我也可以把书的插页放进去,或者把整个事情搞得一团糟。如果有人提出了一种ORM本机方法来满足这种情况,我洗耳恭听:)我能看到这种情况会发生的唯一原因是,如果您同时添加多本书,并且
作者
是通过另一个过程添加的,从您查找它到将该项目添加到收藏中。在我看来,处理这类并发问题的最简单方法是捕获异常,将书附加到数据库中现在的作者,然后重新提交。1。你试过了吗?Author.Books.Add(book);ctx.SaveChangesAsync();2.添加到书中:public int AuthorId{get;set;}public virtual Author Author{get;set;}Claies的观察是正确的……种族正是问题所在,我正试图找到一个解决方法@W92,是的……试过了。同样的竞争条件也会出现。问题在作者插页上。
var author = _ctx.Authors.SqlQuery(
"with data as (select @author as [name]) " +
"merge Authors a " +
"using data s on s.[name] = a.[name] " +
"when not matched by target " +
"then insert([name]) values(s.[name]); select * from Authors where [name]=@author", new SqlParameter("author", command.Author)).Single();
var book = new Book
{
Isbn = command.Id,
Title = command.Title,
Stock = command.Count,
Author = author
};
_ctx.Books.Add(book);
await _ctx.SaveChangesAsync();