我在Entity Framework 6中遇到了一个问题,其中一直抛出异常。在大多数情况下,应用程序完全正常,直到我尝试通过链接表将用户添加到角色。
抛出的错误如下:
无法定义两个对象之间的关系,因为它们附加到不同的ObjectContext对象。
该功能很乐意将用户虚拟地添加到角色中,但只要SaveChanges()
被调用,该过程就会失效。
我知道上述错误的原因和原因以及经过一些研究之后,由于上下文没有被正确处理。因此,继续并查看DbContext设置后,我意识到IDisposable
没有添加到配置中。不幸的是,无论我在应用程序中的任何一点尝试合并IDisposable
仍然没有正确处理上下文。
因此,在花了相当多的时间并且没有通过谷歌运气之后,我想知道你们中是否有人有解决方案或能够指出我正确的方向。
以下是我实施的数据层类的缩减版本:
public class GenericRepository<T> : WebsiteContext, IGenericRepository<T> where T : class
{
public virtual void Commit()
{
SaveChanges();
}
public virtual void Delete(int id)
{
var record = Set<T>().Find(id);
if (record == null)
throw new Exception("Some Message");
Set<T>().Remove(record);
}
// ... ETC
}
public interface IGenericRepository<T> where T : class
{
void Commit();
// ... ETC
}
public class WebsiteContext : DbContext, IWebsiteContext
{
static WebsiteContext()
{
Database.SetInitializer<WebsiteContext>(null);
}
public WebsiteContext() : base("Name=WebsiteContext") { }
public IDbSet<User> Users { get; set; }
// ... ETC
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ... ETC
}
}
此实现基于以下Stackoverflow问题。
Entity Framework 6 Code First - Is Repository Implementation a Good One?
以下是导致此问题的Service Layer类和方法的精简版本。
private IGenericRepository<User> _userRepository;
private IGenericRepository<ApplicationUserSetting> _userSettingRepository;
private IGenericRepository<ApplicationRole> _roleRepository;
public UserManagementService()
{
_userRepository = new GenericRepository<User>();
_roleRepository = new GenericRepository<ApplicationRole>();
_userSettingRepository = new GenericRepository<ApplicationUserSetting>();
}
public void AssignUserRole(AssignRoleModel model)
{
var user = _userRepository.GetById(model.UserId);
if (user == null)
return;
var role = _roleRepository.GetById(model.RoleId);
if (role == null)
return;
user.Roles.Add(role);
_userRepository.Commit();
}
答案 0 :(得分:1)
问题与错误状态一样,是因为您有多个DbContext
类型的实例为您提取实体。然后,每个获取的实体与检索它的DbContext
实例相关联。如果要保留对这些实体的更改,则必须在与其关联的DbContext
实例上进行更改,或者必须将其附加到与之无关的DbContext
实例。
如果您想保持简单,我建议您实施像AutoFac这样的DI框架。然后,您可以为每个请求创建一个DbContext
实例,并将其注入您需要的任何位置。它将允许您保留现有结构(我不会对此进行评论,因为我认为这超出了此问题的范围),最终结果是每个注入GenericRepository
instance有一个注入WebsiteContext
实例,但WebsiteContext
实例是共享的(所有相同的实例)。这样做的好处不再是错误,但缺点是你必须要注意,任何实体的任何更改都会导致这些更改在您执行Save
功能后立即保留。
答案 1 :(得分:0)
使用多个存储库会导致此问题。只需使用一个存储库(=一个数据库上下文),并使用不同的方法获取各个类型。
E.g。 _repository.Get(ID)
答案 2 :(得分:0)
超出范围指出您当前的实施方式如何工作,但如果您确实想要使用多个上下文,您可以尽管其他人有说。
如果这样做,您必须先从上一个上下文detach the entity开始。