0

所以我有一个(新)用户表和一个组表。我想要做的是将用户添加到组中。

我想我会做的是:-

using(context = new MyEntity())
{
    foreach(csvUser from csvSource)
    {
        User oUser = new User();
        oUser.Firstname = csvUser.Firstname;

        Group oGroup = new Group();
        // Set the primary key for attach
        oGroup.ID = csvUser.GroupID;
        context.Group.Attach(oGroup);

        oUser.Groups.Add(oGroup);
        context.Users.Add(oUser);
    }   

    context.saveChnages();
}

所以基本上循环遍历所有新用户,从 CSV 文件中获取他们的组 id(组已经存在于 db 中)。所以我会附加到该组,然后添加该组。

但是,我遇到了一个错误,因为一旦具有已附加组 ID 的用户尝试附加它,它就会爆炸。

在 ObjectStateManager 中找不到具有与所提供对象的键匹配的键的对象。验证所提供对象的键值是否与必须应用更改的对象的键值匹配。

我可以理解,它试图重新附加一个已经附加到内存中的对象。但是有没有办法解决这个问题?我需要做的就是将一个新用户附加到数据库中的一个预先存在的组。

4

3 回答 3

1

该错误通常与ApplyCurrentValues某种形式或形状相关联 - 当它尝试更新您(以前)分离的实体时。

目前尚不完全清楚为什么会在您的情况下发生这种情况-但也许您还有其他事情要做-或者您只是将 EF 与再次附加同一组“混淆”。

我认为最简单的方法就是使用Find- 并避免Attach

context.Group.Find(csvUser.GroupID);  

如果有缓存,则从缓存加载 - 如果需要,则从 Db 加载。

如果上下文中存在具有给定主键值的实体,则立即返回它而不向存储区发出请求。否则,将向存储请求具有给定主键值的实体,如果找到该实体,则将其附加到上下文并返回。如果在上下文或存储中没有找到实体,则返回 null

那应该为您解决问题。

我认为您也可以关闭应用 Db 形式的值(但我目前无法检查)。

于 2013-04-27T22:54:37.197 回答
0

看起来您在用户和组之间存在多对多的关系。如果是这种情况并且您使用的是 Code-First,那么您的模型可以这样定义......

public class User
{
    public int Id { get; set; }
    public string Firstname { get; set; }
    // Other User properties...
    public virtual ICollection<UserGroup> UserGroups { get; set; }
}

public class Group
{
    public int Id { get; set; }
    // Other Group properties...
    public virtual ICollection<UserGroup> UserGroups { get; set; }
}

public class UserGroup
{
    public int UserId { get; set; }
    public User User { get; set; }

    public int GroupId { get; set; }
    public Group Group { get; set; }
}

接下来,配置多对多关系...

public class UserGroupsConfiguration : EntityTypeConfiguration<UserGroup>
{
    public UserGroupsConfiguration()
    {
        // Define a composite key
        HasKey(a => new { a.UserId, a.GroupId });

        // User has many Groups
        HasRequired(a => a.User)
            .WithMany(s => s.UserGroups)
            .HasForeignKey(a => a.UserId)
            .WillCascadeOnDelete(false);

        // Group has many Users
        HasRequired(a => a.Group)
            .WithMany(p => p.UserGroups)
            .HasForeignKey(a => a.GroupId)
            .WillCascadeOnDelete(false);
    }
}

在您的 DbContext 类中添加配置...

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Configurations.Add(new UserGroupsConfiguration());
    ...
}

现在你的任务更简单了......

foreach (var csvUser in csvSource)
{
    User oUser = new User();
    oUser.Firstname = csvUser.Firstname;

    // Find Group
    var group = context.Groups.Find(csvUser.GroupID);

    if(group == null)
    {
       // TODO: Handle case that group is null
    }
    else
    {
        // Group found, assign it to the new user
        oUser.UserGroups.Add(new UserGroup { Group = group });
        context.Users.Add(oUser);
    }
}
context.SaveChanges();
于 2013-04-27T21:19:38.417 回答
0

似乎您正在Group为每个User迭代添加一个新的,试试这个:

using(context = new MyEntity())
{
    // fetch Groups and add them first
    foreach(groupId in csvSource.Select(x => x.GroupID).Distinct())
    {
         context.Groups.Add(new Group { ID = groupId });
    }

    // add users
    foreach(csvUser from csvSource)
    {
        User oUser = new User();
        oUser.Firstname = csvUser.Firstname;

        var existingGroup = context.Groups.Single(x => x.Id == csvUser.GroupID);
        oUser.Groups.Add(existingGroup);

        context.Users.Add(oUser);
    }   

    context.saveChnages();
}
于 2013-04-27T21:27:50.970 回答