Entity Framework Code First Repository действительно универсальный и проблемы с двумя контекстами - PullRequest
0 голосов
/ 31 мая 2011

извините, мой плохой английский. В компании, где я работаю, мы переходим на 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);
        }
      }

но в Entity Framework я не смог реализовать.

еще:

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();
  }

но мне нужен один метод Save для каждого класса Poco

Есть идеи?

Ответы [ 3 ]

0 голосов
/ 31 мая 2011

Вам необходимо разделить контекст EF db между вашими репозиториями.Когда вы извлекаете данные из базы данных через EF, объект, возвращаемый EF, присоединяется к конкретному экземпляру контекста БД для отслеживания изменений.Если вы попытаетесь выполнить какие-либо операции над этим объектом в другом контексте базы данных, EF сгенерирует исключение, так как контекст базы данных может видеть, что он уже подключен к другому контексту.

Обратите внимание, что если это веб-приложение, ваша БДконтекст должен быть разделен только между репозиториями в том же веб-запросе .Если они используются всеми репозиториями для всех веб-запросов, могут возникнуть конфликты.

0 голосов
/ 31 мая 2011

изменить конструктор вашего 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);
        }
   }
0 голосов
/ 31 мая 2011

Это общая проблема.Вы не можете передать сущность, загруженную из одного контекста в другой контекст.Вы должны делиться контекстом между вашими репозиториями при работе в одной единице работы (логическая транзакция).Также достаточно использовать один экземпляр репозитория для каждого типа в единице работы.

Если вы хотите передать сущность из одного контекста в другой контекст, вы должны сначала отсоединить ее от первого контекста, вызвав:

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

Имейте в виду, что если у сущности есть какие-либо загруженные отношения, эти отношения будут потеряны / нарушены, когда вы отсоедините его от контекста.

...