开始学习asp.net和数据库操作。试图实现一些简单的功能 - 两个模型,一个具有对另一个模型的引用列表。
这是我目前收到的错误:
初始化数据库时发生异常。有关详细信息,请参阅InnerException。
内部例外:
无法确定相关操作的有效排序。由于外键约束,模型要求或存储生成的值,可能存在依赖关系。
我的模特:
public class Killer
{
public Killer(string name, string biography)
{
Name = name;
Biography = biography;
KillerId = Guid.NewGuid();
}
public Guid KillerId { get; set; }
public string Name { get; set; }
public string Biography { get; set; }
public virtual Contract Contract { get; set; }
}
public class Contract
{
public Contract(Status status, Killer target, string description, params Killer[] targets)
{
ContractId = Guid.NewGuid();
this.status = status;
Target = target;
Description = description;
Killers = new HashSet<Killer>();
foreach (var t in targets) Killers.Add(t);
}
public Guid ContractId { get; set; }
public enum Status { active, done, failed, rejected, abandoned }
public Status status { get; set; }
public Killer Target { get; set; }
public string Description { get; set; }
//[ForeignKey("ContractID")]
public virtual ICollection<Killer> Killers { get; set; }
}
在上下文中,我使用对象列表初始化db
public class KillerContext : DbContext
{
public DbSet<Killer> Killers { get; set; }
public DbSet<Contract> Contracts { get; set; }
}
在控制器中我做:
KillerContext k = new KillerContext();
public ActionResult Index()
{
var contracts = k.Contracts.ToList();
ViewBag.contracts = contracts;
return View();
}
在Global.asax
:
Database.SetInitializer(new KillerContextInitialization());
以下是我在db中输入第一个数据的方法:
public sealed class KillerContextInitialization : DropCreateDatabaseAlways<KillerContext>
{
protected override void Seed(KillerContext db)
{
List<Killer> killers = new List<Killer>();
//List<Contract> contracts = new List<Contract>();
killers.Add(new Killer(name: "Ivan Firstein", biography: "He was born in the shadows."));
killers.Add(new Killer(name: "Oleg Gazmanov", biography: "test man"));
db.Contracts.Add(new Contract(
Contract.Status.active,
killers.SingleOrDefault(x => x.Name == "Ivan Firstein"),
"KILL OR BE KILLED. As always with love.",
killers.SingleOrDefault(x => x.Name == "Oleg Gazmanov")
));
db.Killers.AddRange(killers);
base.Seed(db);
}
}
答案 0 :(得分:0)
看起来你需要为杀手模型添加ForeignKey属性,并将此密钥存储在属性ContractId中:
public class Killer
{
[ForeignKey(nameof(ContractId)] //Name of added property in line below
public Contract Contract { get; set; } //no need "virtual"
public Guid? ContractId { get; set; }
// other properties...
}
public class Contract
{
[ForeignKey("ContractId")] //Name of added property in Killer Model
public virtual ICollection<Killer> Killers { get; set; }
// other code...
}
修改强>
您应该执行类似于Contract.Target属性的操作:
[ForeignKey(nameof(TargetId)]
public Killer Target { get; set; }
public Guid TargetId { get; set; }
对于枚举类型,您应该添加如下属性:
[Column(nameof(status), TypeName = "int")]
public Status status { get; set; }
答案 1 :(得分:0)
找出问题出在public Killer Target { get; set; }
当我添加数据时,该字段被视为NOT NULL
,我需要做的就是在填充杀手之后保存更改,如下所示:
public sealed class KillerContextInitialization : DropCreateDatabaseAlways<KillerContext>
{
protected override void Seed(KillerContext db)
{
List<Killer> killers = new List<Killer>();
killers.Add(new Killer(name: "Ivan Firstein", biography: "He was born in the shadows."));
killers.Add(new Killer(name: "Oleg Gazmanov", biography: "test man"));
db.SaveChanges(); // - save killers first, then add them to contract
db.Contracts.Add(new Contract(
Contract.Status.active,
killers.SingleOrDefault(x => x.Name == "Ivan Firstein"),
"KILL OR BE KILLED. As always with love.",
killers.SingleOrDefault(x => x.Name == "Oleg Gazmanov")
));
db.Killers.AddRange(killers);
base.Seed(db);
}
}