所以我有一个(新)用户表和一个组表。我要做的是将用户添加到组中。
我以为我会做的是: -
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中找不到。验证密钥值 提供的对象匹配对象的键值 必须应用更改。
我可以理解,它试图重新附加已经附加到内存中的对象。但有没有办法解决这个问题呢?我需要做的就是将新用户从数据库附加到预先存在的组。
答案 0 :(得分:1)
当它尝试更新(先前)分离的实体时,该错误通常与某种形式或形状的ApplyCurrentValues
相关联。
目前还不完全清楚为什么会发生这种情况 - 但也许你还有其他事情要发生 - 或者你只是'混淆'EF与重新连接同一组。
我认为最简单的方法是使用Find
- 并避免使用Attach
context.Group.Find(csvUser.GroupID);
如果有缓存,则从缓存加载 - 如果需要,从Db加载。
如果上下文中存在具有给定主键值的实体, 然后立即返回,而不向商店提出请求。 否则,向商店请求具有给定的实体 主键值和此实体(如果找到)附加到 上下文并返回。如果在上下文中没有找到实体或者 store,然后返回null
那应该为你解决问题。
你也可以关闭我认为的Db值(但我现在无法检查)。
答案 1 :(得分: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();
答案 2 :(得分: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();
}