ASP.NET MVC / Entity Framework: доступ к совокупным объектам через сводный корневой репозиторий - PullRequest
2 голосов
/ 05 августа 2010

Я нахожусь в процессе создания моего первого веб-приложения с использованием ASP.NET MVC 2 и Entity Framework.Я использую шаблон хранилища.Из информации, которую я собрал о переполнении стека и других веб-сайтах, выясняется, что единодушным является единый контроллер на каждый объект модели домена и один репозиторий на совокупный корневой объект.агрегатные объекты без полномочий root через сводный корневой репозиторий.В примере, с которым я имею дело, есть модель Customer и модель Boat.Лодки могут существовать только с указанием FK на Клиента, и на Лодки нужно ссылаться только в контексте Клиента.Это заставило меня поверить, что у меня был агрегат с этими двумя объектами и что клиент был корнем.

Теперь в моем контроллере Boats у меня есть метод действия Edit:

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
    }
}

MyВопрос в том, как мне получить объект «Лодка» в репозитории?

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

Допустимо ли ссылаться на db.Boats из репозитория клиентов?Это кажется самым чистым, но это означало бы, что мне пришлось бы изменить свой FakeCustomersRepository, чтобы иметь список клиентов и лодок.

Мне казалось более разумным доступ к лодке через db.Customers, однакоЯ не мог понять, как вернуть один объект Boat, не повторяя себя в запросе LINQ, который действительно мне не понравился.

Я знаю, что мне еще многое предстоит узнать, так что надеюсь, вы сможете указатьменя в правильном направлении!

Спасибо!

Ответы [ 2 ]

1 голос
/ 06 августа 2010

По моему мнению, вы говорите о деталях реализации, а не о ваших абстрактных интерфейсах и вашей модели.Ваш интерфейс выглядит следующим образом:

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

, а модель выглядит следующим образом:

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

Я считаю, что это не противоречит каким-либо правилам проектирования, чтобы реализация ICustomerRepository была совершенно иной дляваш SQLCustomersRepository и для вашего FakeCustomersRepository и найти реализацию, которая является оптимальной по отношению к вашему базовому хранилищу данных.

Так как у вас, кажется, есть первичный ключ в таблице Boat в вашей SQL-DB, яопределенно воспользуется этим и реализует первый вариант: return db.Boats.SingleOrDefault(x => x.ID == id);

Но не обязательно иметь коллекцию лодок в вашем FakeCustomersRepository.Если вам проще иметь список клиентов и заполнить коллекцию лодок в каждом клиенте тестовыми лодками, почему бы и нет?В этом случае ваша реализация GetBoat в FakeCustomersRepository может быть реализована с помощью второго запроса LINQ, который вы описали.

Имейте в виду, что модульное тестирование в MVC не предназначено для тестирования ваших конкретных реализаций репозитория, но вашабизнес-логика и бизнес-действие - это скорее цепочка вызовов различных объектов и методов репозитория.Если один метод репозитория делает то, что должен (например, если GetBoat действительно возвращает лодку с правильным идентификатором), это скорее вопрос более позднего интеграционного теста, чтобы доказать, что вызовы вашей базы данных работают правильно.

0 голосов
/ 05 августа 2010

Почему у вас нет хранилища лодок?

Если Лодка - AggRoot, у вас должен быть отдельный репозиторий для нее.

...