Padrão de repositório com o Entity Framework 4.1 e relacionamentos pai / filho

Ainda tenho alguma confusão com o Padrão de Repositório. A principal razão pela qual desejo usar esse padrão é evitar chamar operações de acesso a dados específicas do EF 4.1 do domínio. Prefiro chamar operações CRUD genéricas a partir de uma interface IRepository. Isso tornará os testes mais fáceis e, se precisar alterar a estrutura de acesso a dados no futuro, poderei fazê-lo sem refatorar muito códig

Aqui está um exemplo da minha situação:

Tenho 3 tabelas no banco de dados:Group, Person eGroupPersonMap. GroupPersonMap é uma tabela de links e consiste apenas noGroup ePerson chaves primárias. Criei um modelo EF das 3 tabelas com o designer do VS 2010. A EF foi esperta o suficiente para assumirGroupPersonMap é uma tabela de links para que não seja exibida no designer. Quero usar meus objetos de domínio existentes em vez das classes geradas pela EF, por isso desativo a geração de código para o model

Minhas classes existentes que correspondem ao modelo EF são as seguintes:

public class Group
{
   public int GroupId { get; set; }
   public string Name { get; set; }

   public virtual ICollection<Person> People { get; set; }
}

public class Person
{
   public int PersonId {get; set; }
   public string FirstName { get; set; }

   public virtual ICollection<Group> Groups { get; set; }
}

Eu tenho uma interface de repositório genérica assim:

public interface IRepository<T> where T: class
{
    IQueryable<T> GetAll();
    T Add(T entity);
    T Update(T entity);
    void Delete(T entity);
    void Save()
}

e um repositório EF genérico:

public class EF4Repository<T> : IRepository<T> where T: class
{
    public DbContext Context { get; private set; }
    private DbSet<T> _dbSet;

    public EF4Repository(string connectionString)
    {
        Context = new DbContext(connectionString);
        _dbSet = Context.Set<T>();
    }

    public EF4Repository(DbContext context)
    {
        Context = context;
        _dbSet = Context.Set<T>();
    }

    public IQueryable<T> GetAll()
    {
        // code
    }

    public T Insert(T entity)
    {
        // code
    }

    public T Update(T entity)
    {
        Context.Entry(entity).State = System.Data.EntityState.Modified;
        Context.SaveChanges();
    }

    public void Delete(T entity)
    {
        // code
    }

    public void Save()
    {
        // code
    }
}

gora, suponha que eu apenas queira mapear umGroup para um @ existenPerson. Eu teria que fazer algo como o seguinte:

        EFRepository<Group> groupRepository = new EFRepository<Group>("name=connString");
        EFRepository<Person> personRepository = new EFRepository<Person>("name=connString");

        var group = groupRepository.GetAll().Where(g => g.GroupId == 5).First();
        var person = personRepository.GetAll().Where(p => p.PersonId == 2).First();

        group.People.Add(person);
        groupRepository.Update(group);

Mas isso não funciona porque a EF pensa quePerson é novo e tentará reINSERT aPerson no banco de dados que causará um erro de restrição de chave primária. Eu devo usarDbSet 'sAttach para informar à EF que oPerson já existe no banco de dados, então apenas crie um mapa entreGroup ePerson noGroupPersonMap mesa

Então, para anexarPerson para o contexto, agora devo adicionar umAttach método para meu IRepository:

public interface IRepository<T> where T: class
{
    // existing methods
    T Attach(T entity);
}

Para corrigir o erro de restrição de chave primária:

EFRepository<Group> groupRepository = new EFRepository<Group>("name=connString");
EFRepository<Person> personRepository = new EFRepository<Person>(groupRepository.Context);

var group = groupRepository.GetAll().Where(g => g.GroupId == 5).First();
var person = personRepository.GetAll().Where(p => p.PersonId == 2).First();

personRepository.Attach(person);
group.People.Add(person);
groupRepository.Update(group);

Fixo. Agora eu tenho que lidar com outra questão em queGroup está sendo atualizado no banco de dados toda vez que crio um mapa de grupo / pessoa. Isso ocorre porque no meuEFRepository.Update(), o estado da entidade é explicitamente definido comoModified'. I must set the Group's state to Inalteradoso the tabela do grupo não é modificad

Para corrigir isso, devo adicionar algum tipo deUpdate sobrecarga no meu IRepository que não atualiza a entidade raiz ouGroup, nesse caso

public interface IRepository<T> where T: class
{
    // existing methods
    T Update(T entity, bool updateRootEntity);
}

A implementação EF4 do método Update seria algo como isto:

T Update(T entity, bool updateRootEntity)
{
   if (updateRootEntity)
      Context.Entry(entity).State = System.Data.EntityState.Modified;
   else
      Context.Entry(entity).State = System.Data.EntityState.Unchanged;

    Context.SaveChanges();
}

Minha pergunta é: estou abordando isso da maneira certa? Meu Repositório está começando a parecer centrado no EF à medida que começo a trabalhar com o EF e o padrão do repositório. Obrigado por ler este longo post

questionAnswers(1)

yourAnswerToTheQuestion