实体框架代码第一个存储库真的是通用的和两个上下文的问题

时间:2011-05-31 14:13:33

标签: c# repository-pattern entity-framework-4.1

抱歉,我的英语不好。 在我工作的公司,我们正在迁移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();
  }

但是我需要为每个classe Poco提供一个Save方法

任何想法?

3 个答案:

答案 0 :(得分:0)

这是常见问题。您无法将从一个上下文加载的实体传递到另一个上下文。在一个工作单元(逻辑事务)中工作时,您应该在您的存储库之间共享上下文。在工作单元中每种类型使用一个存储库实例也足够了。

如果要将实体从一个上下文传递到其他上下文,则必须先通过调用将其从第一个上下文中分离出来:

ctx.Entry(entity).State = EntityState.Detached;

请注意,如果实体具有任何已加载的关系,则当您将其从上下文中分离时,这些关系将会丢失/损坏。

答案 1 :(得分:0)

您需要在存储库之间共享EF db上下文。通过EF从数据库检索数据时,EF返回的对象将附加到数据库上下文的特定实例以进行更改跟踪。如果您尝试在另一个数据库上下文中对该实体执行任何操作,EF将抛出异常,因为数据库上下文可以看到它已经附加到另一个上下文。

请注意,如果这是一个Web应用程序,则只应在同一Web请求中的存储库之间共享您的数据库上下文。如果它们在所有Web请求的所有存储库之间共享,则会发生冲突。

答案 2 :(得分:0)

更改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);
        }
   }