这是我第一次使用EF,所以我可能会做一些愚蠢的事情。欢迎任何关于架构的评论。
所以我有典型的用户类。用户拥有用户名和角色列表:
public class User
{
public string UserID{ get; set; }
public List<Role> Roles { get; set; }
public int Id { get; set; }
public User()
{
Roles = new List<Role>();
}
}
我的域对象与他们的存储库的接口一起存在于他们自己的代码库中。所以在这种情况下,会有一个IUserRepository包含所有CRUD方法以及我可能需要的任何专用数据访问方法。我要做的是在另一个类库中使用EF4实现这些存储库接口。到目前为止,这个设计有任何问题吗?
现在在db(sql server)中我有一些典型的表:用户,角色和多对多表将用户映射到角色UsersRoles。
我已经在EF lib中成功设置了大多数CRUD方法。这是Save的样子
public void Save(Drc.Domain.Entities.Staff.User member)
{
using (var ctx = new DrcDataContext())
{
var efUser = MapFromDomainObject(member);
if(member.Id < 1)
{
ctx.Users.AddObject(efUser);
}
else
{
ctx.Users.Attach(efUser);
ctx.ObjectStateManager.ChangeObjectState(efUser, EntityState.Modified);
}
ctx.SaveChanges();
member.Id = efUser.UserId;
}
}
现在我不确定这是否是实现这一目标的正确方法,但它确实有效。但是,在执行删除时遇到问题。问题在于相关表格
public void Delete(Drc.Domain.Entities.Staff.User member)
{
using (var ctx = new DrcDataContext())
{
var efUser = MapFromDomainObject(member); ctx.Users.Attach(efUser);
while (efUser.Roles.Count > 0)
{
ctx.ObjectStateManager.ChangeObjectState(efUser.Roles.First(), EntityState.Deleted);
}
ctx.SaveChanges();
ctx.ObjectStateManager.ChangeObjectState(efUser, EntityState.Deleted);
ctx.SaveChanges();
}
}
如果我不删除while循环中的角色,则会出现与引用约束错误的DELETE冲突。如果我运行上面的代码,它确实删除了多对多表中的正确行,但它也删除了Roles表中的行。我现在处于死胡同,正在考虑抓住ORM的想法并将我的存储库实现编写在良好可靠的ADO.net中。
- 编辑我猜这不是用EF实现存储库的正确方法。是不是可以不用乱扔垃圾的东西乱扔你的域名?
答案 0 :(得分:0)
简单地使用标准方法,不要乱用实体状态:
public void Delete(Drc.Domain.Entities.Staff.User member)
{
using (var ctx = new DrcDataContext())
{
var efUser = MapFromDomainObject(member);
ctx.Users.Attach(efUser);
ctx.Users.DeleteObject(efUser);
ctx.SaveChanges();
}
}
数据库中从User
表到连接表通常会有级联删除(如果你没有手动禁用它)。因此,删除用户也将删除连接表中的相应行(当然不是角色)。
将实体的状态设置为Deleted
与调用DeleteObject
不同。它只会将父项设置为已删除,并将子项保留在上下文中的未删除状态,从而导致约束违例异常。 DeleteObject
还会将上下文中的孩子标记为Deleted
,从而避免例外。