【问题标题】:EF 4.3 Many to Many Relation and Junction Table UpdateEF 4.3 多对多关系和连接表更新
【发布时间】:2012-04-08 01:48:03
【问题描述】:
public class User
{
    public int Id{ get; set; }
    public ICollection<UserAction> UserActions{ get; set; }
    public string Name{ get; set; }
}

public class Action
{
    public int Id{ get; set; }
    public string Name{ get; set; }
    public ICollection<UserAction> UserActions{ get; set; }
}

public UserAction
{
    public int Id{ get; set; }
    public User User{ get; set; }
    public Action Action{ get; set; }
    public int Type {get;set}       
}

在存储库类中

public void Update(User user,List<UserAction> actions)
{
    User entity = this.GetUser(user.Id);           
    entity.UserActions.Clear();
    entity.UserActions= actions;
    this.siteRepository.Update<SiteUser>(user);
    this.siteRepository.UnitOfWork.SaveChanges();
}

我在下面遇到错误,例如

操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为外键属性分配另一个非空值,或者必须删除不相关的对象。

【问题讨论】:

  • 不清楚你在问什么。更新应该做什么?您传入的 UserAction 实例是否已经具有要更改的用户和与之关联的操作?你能解释一下你想做什么,而不仅仅是发布代码吗?
  • 你知道 EF 的多对多关系吗?就是这样。
  • 您在示例中所拥有的并不是 EF 认为的多对多关系,因为您已经映射了连接表。映射连接表很好。但是你想做什么?
  • 映射很好但是,我没有删除联结表数据,通常如果联结表中没有Type属性,它很容易。
  • 您得到的异常表明您有一个 FK 映射到某个属性。我在您发布的任何代码中都没有看到 FK 映射。您能否更新包含 FK 属性的代码或在代码中指出您已将哪个属性映射到 FK?

标签: c# .net entity-framework entity-framework-4.3


【解决方案1】:

如果您想用传递给方法的新集合替换数据库中现有的UserActions 集合,您将需要这样的东西。特别是有必要删除已从集合中删除的UserActions 也从数据库中删除,因为显然关系是必需的,并且用户操作必须引用用户实体或必须删除(这就是异常所说的):

User entity = context.Users.Include(u => u.UserActions)
    .Single(u => u.Id == user.Id);

context.Entry(entity).CurrentValues.SetValues(user);
foreach (var userAction in entity.UserActions.ToList())
    if (!user.UserActions.Any(ua => ua.Id == userAction.Id))
        context.UserActions.Remove(userAction);   // DELETE is important here!

foreach (var userAction in user.UserActions)
{
    var userActioninDB = entity.UserActions
        .SingleOrDefault(ua => ua.Id == userAction.Id);
    if (userActionInDB == null)
        entity.UserActions.Add(userActioninDB);
    else
        context.Entry(userActioninDB).CurrentValues.SetValues(userAction);
}

context.SaveChanges();

您必须将其转换为您的存储库结构。

【讨论】:

  • 您添加 UserActions 行的行不应该是entity.UserActions.Add(userAction) 吗?
【解决方案2】:

谢谢Slauma,解决办法是

List<UserAction> actions = new List<UserAction>(user.UserActions.ToList());

foreach (var action in actions )
{
  Delete<UserAction>(action);
}

【讨论】:

    【解决方案3】:

    将用户集合添加到操作类和操作到用户。如果 user 和 action 对这个表是唯一的,你甚至不能映射 UserAction 表。

    我在这里的回答完全一样: Database First with Bridge Table, How to Keep It Out of Model

    【讨论】:

    • 是的,知道但我的桥表有一个字段,它由 Type 调用,我不隐藏那个 UserAction
    • 所以只需使用 UserAction 添加实体,这是唯一的方法。当然,您可以使用添加的操作或用户实体方法,但无论如何,首先您必须创建 UserAction 实体
    • 不,这不可能,我必须在联结表中使用 Type 属性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-03
    • 1970-01-01
    • 1970-01-01
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多