首先是实体框架代码,通过更新父代删除子代

时间:2013-07-31 21:17:01

标签: asp.net-mvc-4 ef-code-first entity-framework-5

当实体框架声明“代码优先”时,我们首先使用代码...

public class BaseModel
{
    [Key]
    public Guid Id { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateChanged { get; set; }

    public BaseModel()
    {
        this.Id = Guid.NewGuid();
        this.DateCreated = DateTime.Now;
        this.DateChanged = DateTime.Now;
    }
}

public class Association: BaseModel
{
    public string Name { get; set; }
    public string Type { get; set; }

    public virtual List<Rule> Rules { get; set; }

    public Association()
        : base()
    {
    }
}

public class Rule: BaseModel
{
    [ForeignKey("Association")]
    public Guid AssociationId { get; set; }

    //[Required]
    public virtual Association Association { get; set; }

    //[Required]
    public string Name { get; set; }

    public string Expression { get; set; }

    public virtual List<Action> Actions { get; set; }

    public Rule()
        : base()
    {
    }
}

public class Action: BaseModel
{
    public string Name { get; set; }

    public string ActionType { get; set; }

    [ForeignKey("Rule")]
    public Guid RuleId { get; set; }

    public virtual Rule Rule { get; set; }

    public int Order { get; set; }

    public Action()
        : base()
    {
    }
}

所以这些是我的四个模型类,它们首先使用实体​​框架代码。 每个都从基类继承,因此它们都有一个Id Guid作为主键。

协会有一系列规则。 (规则有FK到协会) 规则具有操作列表。 (行动有FK规则)

我想做的只是更改并保存最上层的课程=协会。 例如,当删除规则时,我希望此代码可以工作:

 public ActionResult DeleteRule(Guid assId, Guid ruleId)
    {
        Association ass = this.DataContext.Associations.FirstOrDefault(a => a.Id == assId);
        ass.Rules.RemoveAll(r => r.Id == ruleId);

        this.DataContext.SaveChanges();

        return RedirectToAction("Index");
    }

在context.savechanges上,这给了我这个错误: '操作失败:由于一个或多个外键属性不可为空,因此无法更改关系。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。'

删除操作时也会发生此错误。

有没有办法更改最上层(关联)对象,只能更改此关联。 我不想说context.Rules.remove(...)或context.actions.remove(...)

这是来源:http://server.thomasgielissen.be/files/mvctesting.zip 你需要VS2012,所有nuget包都包含在zip中,你应该能够构建和运行项目。

提前感谢您的反馈!

格尔茨, 托马斯

1 个答案:

答案 0 :(得分:0)

我想解决这个问题,你应该通过联结表存储关系。我不认为你可以通过这个模型实现你所需要的。

但是,如果在实体之间放置联结表(或实体),则可以轻松删除子对象并更新父对象。

例如,将联结实体放在AssociationRule之间:

public class AssociationRule: BaseModel
{
    public Guid AssociationId { get; set; }
    public Guid RuleId { get; set; }

    [ForeignKey("AssociationId")]
    public virtual Association Association { get; set; }
    [ForeignKey("RuleId")]
    public virtual Rule Rule { get; set; }        

    public Association()
        : base()
    {
    }
}

现在,您可以轻松删除任何关联中的任何规则:

public ActionResult DeleteRule(Guid assId, Guid ruleId)
{
    AssociationRule assr = this.DataContext
        .AssociationRuless
        .FirstOrDefault(ar => ar.AssociationId == assId && ar.RuleId == ruleId);

    this.DataContext.AssociationRules.Remove(assr);
    this.DataContext.SaveChanges();

    return RedirectToAction("Index");
}