Entity Framework Code First Repository 真的很通用并且有两个上下文的问题
Posted
技术标签:
【中文标题】Entity Framework Code First Repository 真的很通用并且有两个上下文的问题【英文标题】:Entity Framework Code First Repository really generic and problems with two context 【发布时间】:2011-05-31 14:13:32 【问题描述】:对不起,我的英语不好。 在我工作的公司中,我们正在迁移到 Entity Framework Code First。 但是当我创建两个存储库实例时会出现问题
RepositoryGeneric<Anuncio> repAnuncio1 = new RepositoryGeneric<Anuncio>();
Anuncio anuncio1 = repAnuncio1.find(1)
Anuncio anuncio2 = new Anuncio (1,20,"any thing");
RepositoryGeneric<Anuncio> repAnuncio2 = new RepositoryGeneric<Anuncio>();
repAnuncio2.salvar(anuncio2); //ok work
repAnuncio2.salvar(anuncio1); // error the anuncio1 is atach in repAnuncio1
这只是一个例子,但在实际应用中我需要多个存储库交互。
否则,我们的应用程序使用 DataContext:
public static void Save(Entity entity)
if (entity != null)
SqlServer sql = new SqlServer();
Type tipoEntidade = entity.GetType();
PropertyInfo[] propriedades = tipoEntidade.GetProperties();
foreach (PropertyInfo propriedade in propriedades)
if (propriedade.PropertyType.IsPublic && propriedade.CanWrite && propriedade.PropertyType.Namespace == "System")
object valor = propriedade.GetValue(entidade, null);
if (valor != null && propriedade.Name != "ID" && propriedade.Name != "Excluido")
sql.AdicionarParametro("@" + propriedade.Name, valor);
但在实体框架中我无法实现。
其他:
public int Save(Anuncio anuncio)
if (anuncio.Id != 0)
// ctx.Anuncio.Attach(anuncio);
//attach Error when othe repository get
//else i need...
BancoContext ctx = new BancoContext (); //my Dbcontext
AnuncioAxiliar = ctx.Anuncio.FirstOrDefault(x => x.Id == entidade.Id); //Entity help
AnuncioAxiliar.Nome = anuncio.Nome;
AnuncioAxiliar.Cliente= anuncio.Cliente;
AnuncioAxiliar.Contrato= anuncio.Contrato;
ctx.SaveChanges(); //vai salvar o AnuncioAxiliar
else
ctx.Set(entidade.GetType()).Add(entidade);
return ctx.SaveChanges();
但是我需要为每个类 Poco 提供一个 Save 方法
有什么想法吗?
【问题讨论】:
【参考方案1】:这是常见的问题。您不能将从一个上下文加载的实体传递到另一个上下文。在一个工作单元(逻辑事务)中工作时,您应该在存储库之间共享上下文。在工作单元中,每种类型使用一个存储库实例也足够了。
如果你想将实体从一个上下文传递到另一个上下文,你必须首先通过调用将它从第一个上下文中分离出来:
ctx.Entry(entity).State = EntityState.Detached;
请注意,如果实体有任何已加载的关系,当您将其从上下文中分离出来时,这些关系将会丢失/破坏。
【讨论】:
但大多数情况下,另一个类中的一个方法将接收实体保存与否并返回第一个方法,使我无法分离 所以为逻辑事务使用一个上下文。这就是重点。在这种情况下使用多个上下文是完全错误的用法。【参考方案2】:您需要在存储库之间共享 EF db 上下文。当您通过 EF 从数据库中检索数据时,EF 返回的对象将附加到 db 上下文的特定实例以进行更改跟踪。如果您尝试在另一个数据库上下文中对该实体执行任何操作,EF 将抛出异常,因为数据库上下文可以看到它已经附加到另一个上下文。
请注意,如果这是一个 Web 应用程序,您的 db 上下文应该只在存储库之间共享仅在同一个 Web 请求中。如果它们在所有 Web 请求的所有存储库之间共享,则会发生冲突。
【讨论】:
【参考方案3】:更改 RepositoryGeneric 的构造函数以接受您的数据上下文作为参数。然后对所有存储库使用相同的上下文。您可能应该使用依赖注入来实现这一点。
类似下面的东西
public class RepositoryGeneric<TEntity>
public RepositoryGeneric(DomainContext domainContext)
DomainContext = domainContext;
protected DomainContext DomainContext get; private set;
protected virtual IDbSet<TEntity> DbSet
get return DomainContext.Set<TEntity>();
public virtual TEntity GetByKey(params object[] keys)
return DbSet.Find(keys);
【讨论】:
以上是关于Entity Framework Code First Repository 真的很通用并且有两个上下文的问题的主要内容,如果未能解决你的问题,请参考以下文章
Entity Framework 5.0 Code First全面学习
ADO.NET Entity Framework -Code Fisrt 开篇
转:Entity Framework 5.0 Code First全面学习