在Entity Framework中存储自定义对象的列表

时间:2017-11-17 14:32:12

标签: c# sql-server asp.net-mvc entity-framework

开始学习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);
    }
}

2 个答案:

答案 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);
        }
    }