【发布时间】:2012-02-17 20:38:48
【问题描述】:
编辑:在这个问题的底部回答
好的,我有一些通用的 EF 函数(其中大部分是从这里得到的),但它们似乎不起作用。
我有 3 节课:
public class Group : Entity
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual GroupType GroupType { get; set; }
public virtual ICollection<User> Users { get; set; }
}
public class GroupType: Entity
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class User: Entity
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public virtual ICollection<Group> Groups { get; set; }
}
我的 CRUD 操作:
public void Insert(TClass entity)
{
if (_context.Entry(entity).State == EntityState.Detached)
{
_context.Set<TClass>().Attach(entity);
}
_context.Set<TClass>().Add(entity);
_context.SaveChanges();
}
public void Update(TClass entity)
{
DbEntityEntry<TClass> oldEntry = _context.Entry(entity);
if (oldEntry.State == EntityState.Detached)
{
_context.Set<TClass>().Attach(oldEntry.Entity);
}
oldEntry.CurrentValues.SetValues(entity);
//oldEntry.State = EntityState.Modified;
_context.SaveChanges();
}
public bool Exists(TClass entity)
{
bool exists = false;
if(entity != null)
{
DbEntityEntry<TClass> entry = _repository.GetDbEntry(entity);
exists = entry != null;
}
return exists;
}
public void Save(TClass entity)
{
if (entity != null)
{
if (Exists(entity))
_repository.Update(entity);
else
_repository.Insert(entity);
}
}
最后我用下面的方法调用这段代码:
public string TestCRUD()
{
UserService userService = UserServiceFactory.GetService();
User user = new User("Test", "Test", "Test", "TestUser") { Groups = new Collection<Group>() };
userService.Save(user);
User testUser = userService.GetOne(x => x.UserName == "TestUser");
GroupTypeService groupTypeService = GroupTypeServiceFactory.GetService();
GroupType groupType = new GroupType("TestGroupType2", null);
groupTypeService.Save(groupType);
GroupService groupService = GroupServiceFactory.GetService();
Group group = new Group("TestGroup2", null) { GroupType = groupType };
groupService.Save(group);
user.Groups.Add(group);
userService.Save(user);
return output;
}
当我到达:
user.Groups.Add(group);
userService.Save(user);
我收到以下错误:
保存不为其关系公开外键属性的实体时发生错误。 EntityEntries 属性将返回 null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常。有关详细信息,请参阅 InnerException。
有以下内部异常:
INSERT 语句与 FOREIGN KEY 约束“User_Groups_Source”冲突。冲突发生在数据库“DBNAME”、表“dbo.Users”、列“Id”中。
问题:
1) Exists 始终返回 true,即使该实体刚刚在内存中创建,因此 insert 实际上从未在 Save 方法内仅被调用 Update,我想这是因为我不了解 DbEntityEntry完全是因为它本身和 Entry.Entity 都永远不会为空。如何检查是否存在?
2) 尽管所有代码都在 TestCRUD 中运行到最后,但实际上并没有将这些实体保存到数据库中。我很肯定我的数据库设置正确,因为我的自定义初始化程序总是删除和重新创建数据库,并且每次都插入种子数据。这可能是因为更新总是被调用,如数字 1 中所述。
任何想法如何解决?
编辑:答案
正如假设的那样,问题是 Exists 总是返回 true,因此永远不会调用 insert。我通过使用反射来获取主键并将其插入到 find 方法中来解决这个问题,如下所示:
public bool Exists(TClass entity)
{
bool exists = false;
PropertyInfo info = entity.GetType().GetProperty(GetKeyName());
if (_context.Set<TClass>().Find(info.GetValue(entity, null)) != null)
exists = true;
return exists;
}
所有其他方法都按预期开始工作。但是,我在同一行遇到了不同的错误:
user.Groups.Add(group);
userService.Save(user);
原来是:
违反主键约束“PK_GroupTypes_00551192”。无法在对象“dbo.GroupTypes”中插入重复键。 声明已终止。
我将把它作为一个新问题发布,因为它是一个新错误,但它确实解决了第一个问题。
【问题讨论】:
-
将实体附加到上下文后,您应该将其状态设置为添加或修改。请参阅 ObjectStateManager.ChangeObjectState 方法。但是在保存用户之前不能说为什么你的 Exists 方法会给你真实的。
-
@ElDog 我试过了(你可以看到它在更新中被注释掉了),它抛出了一个错误,说不能这样做,因为实体在操作之间被修改或删除或其他什么效果。
标签: c# asp.net-mvc-3 entity-framework ef-code-first crud