ASP.NET MVC/ENTITY Framework: Acessando objetos agregados através do repositório raiz agregado

StackOverflow https://stackoverflow.com/questions/3417769

Pergunta

Estou em processo de criação do meu primeiro aplicativo da Web usando o ASP.NET MVC 2 e o Entity Framework. Estou usando o padrão do repositório. A partir de informações, reuni no Stack Overflow e em outros sites, parece que o consenso é ter um controlador por objeto de modelo de domínio e um repositório por objeto raiz agregado.

A pergunta que tenho é como devo acessar objetos agregados sem raios através do repositório raiz agregado. No exemplo com o qual estou lidando, há um modelo de cliente e um modelo de barco. Os barcos só podem existir com uma referência de FK a um cliente e os barcos só precisam ser referenciados no contexto de um cliente. Isso me levou a acreditar que eu tinha um agregado com esses dois objetos e que o cliente era a raiz.

Agora, no meu controlador de barcos, tenho um método de ação de edição:

public class BoatsController : Controller
{
    private ICustomersRepository customersRepository;
    public BoatsController(ICustomersRepository customersRepository)
    {
        this.customersRepository = customersRepository;
    }   
    public JsonResult Edit(int id, FormCollection collection)
    {
        var boat = customersRepository.GetBoat(id);
        // Update boat
    }
}

Minha pergunta é como quero recuperar o objeto de barco no repositório?

public class SQLCustomersRepository : ICustomersRepository
{
    DatabaseEntities db = new DatabaseEntities();

    public Boat GetBoat(int id)
    {
        return db.Boats.SingleOrDefault(x => x.ID == id);

        // OR

        return db.Customers.Where(x => x.Boats.Any(y => y.ID == id)
                           .Select(x => x.Boats.FirstOrDefault(y => y.ID == id);
    }
}

É aceitável para mim fazer referência a DB.Boats do repositório de clientes? Parece ser o mais limpo, mas significaria que eu teria que alterar meu FakecustomersRepository para ter uma lista de clientes e barcos.

Pareceu -me mais razoável acessar o barco através de db.customers, no entanto, eu não conseguia descobrir como devolver um único objeto de barco sem me repetir na consulta do LINQ que realmente não se encaixava bem comigo.

Eu sei que ainda tenho muito a aprender, então espero que você possa me apontar na direção certa!

Obrigado!

Foi útil?

Solução

Na minha opinião, você está falando sobre detalhes da implementação, não sobre suas interfaces abstratas e seu modelo. Sua interface parece ser assim:

public interface ICustomersRepository
{
    //... other methods
    Boat GetBoat(int id);
    //... other methods
}

E o modelo como este:

public class Customer
{
    //... other stuff
    ICollection<Boat> Boats; // or another collection type
    //... other stuff
}

Na minha opinião, não é contra nenhuma regra de design implementar o icustomerRepository completamente diferente para o seu SQLCustomersRepository e para o seu FakeCustomersRepository e encontrar uma implementação ideal em relação ao seu armazenamento de dados subjacentes.

Como você parece ter uma chave primária na mesa de barco em seu SQL-DB, eu definitivamente aproveitaria isso e implementaria a primeira opção: return db.Boats.SingleOrDefault(x => x.ID == id);

Mas não é necessário ter uma coleção de barcos em seu FakeCustomersRepository. Se for mais fácil para você apenas ter uma lista de clientes e preencher a coleção de barcos em cada cliente com barcos de teste, por que não? Neste caso, seu GetBoat implementação no FakeCustomersRepository pode ser implementado com a segunda consulta LINQ que você descreveu.

Lembre -se de que o teste de unidade no MVC não pretende testar suas implementações específicas de repositório, mas sua lógica de negócios, e uma ação comercial é mais uma cadeia de vários objetos de domínio e chamadas de método repositório. Se um único método de repositório faz o que deveria fazer (por exemplo, se GetBoat Realmente retorna um barco com o ID correto) é mais uma questão de um teste de integração posterior para provar que suas chamadas de banco de dados funcionam corretamente.

Outras dicas

Por que você não tem um repositório de barco?

Se o barco for um agrupamento, você deve ter um repositório separado para ele.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top