Рекомендации по проектированию объектов сопоставления Linq to SQL

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

Скажем, у меня есть две таблицы БД:

User
----
Id
Name


Phone
-----
Id
UserId
Model

Генератор кода Linq создает несколько классов сущностей.

Затем я пишу свои собственные классы и интерфейсы, которые обертывают эти классы Linq:

class DatabaseUser : IUser
{
    public DatabaseUser(User user)
    {
        _user = user;
    }

    public Guid Id 
    {
        get { return _user.Id; } 
    }

    ... etc
}

Все идет нормально.

Теперь достаточно просто найти пользователей телефонов из Phones.Where(p => p.User = user) но, конечно же, пользователям API не нужно писать свои собственные запросы Linq для получения данных, поэтому я должен заключить этот запрос в функцию или свойство где-нибудь.

Таким образом, вопрос в том, добавите ли вы свойство Phones в IUser или нет?

Другими словами, должен ли мой интерфейс специально моделировать объекты моей базы данных (в этом случае телефоны не принадлежат IUser), или они на самом деле просто предоставляют набор функций и свойств, которые концептуально связаны с пользователем (в этом случае он делает)?

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

Моей первой мыслью было использовать методы расширения, но на самом деле это не работает в этом случае.

4 ответа

Решение

У меня был ужасный опыт, когда я пытался абстрагировать сущности LINQtoSQL за интерфейсами. Это было некоторое время назад, но по памяти основная проблема заключалась в том, что это полностью разрушает ассоциации. Например, если у вас есть Customer -> Order отношения, вы заканчиваете тем, что выставляете это как ICustomer, с коллекцией IOrderс, что означает, что Customer должен сделать какое-то неловкое отображение, чтобы наложить его внутреннюю коллекцию Order объекты как IOrders.

Тогда вы должны предположить, что когда IOrder передается обратно, что мы можем привести его к Order, В противном случае LINQtoSQL не сможет справиться с этим, но тогда это лишит смысла наличие интерфейса в первую очередь.

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

Аспекты, которые я хотел бы скрыть за интерфейсом, это взаимодействие с DataContext, например, с использованием классов в стиле репозитория:

public interface IPhoneRepository 
{
    IEnumerable<Phone> GetPhonesForUser(User user);
}

public class L2SPhoneRepository : IPhoneRepository
{
    private readonly MyDataContext context;

    public L2SPhoneRepository(MyDataContext context)
    {
        this.context = context;
    }

    public IEnumerable<Phone> GetPhonesForUser(User user)
    {
        return context.Phones.Where(p => p.User == user);
    }
}

Я склонен считать, что связанные с Linq2Sql вещи являются деталями реализации кода доступа к данным и, как и реальная структура базы данных, не обязательно должны подвергаться воздействию других частей системы.

Если ваш API будет использоваться другими людьми, он должен быть сплоченным и простым в использовании и не загроможденным вещами, о которых потребитель не должен знать. Если я имею дело с пользователями и их телефонами, я действительно не хочу знать о DataContexts или (тьфу) DataSets.

Кроме того, сохраняя большую часть своего кода в неведении о L2S и базе данных, вам будет проще проводить тестирование, вносить изменения в схему (о, теперь в таблице User необходимо вести историю каждого внесенного изменения) или даже полностью менять ORM.,

Вы должны добавить свойство Phones в IUser и сделать его обнуляемым, поэтому для пользователя, у которого нет Phone, оно будет нулевым.

Поскольку вы не хотите, чтобы потребители API писали запросы, вам следует реализовать такие функции, как GetUser() и т. Д.

Вот хороший список статей abt n-уровневого приложения в Asp.net

http://imar.spaanjaars.com/QuickDocId.aspx?quickdoc=416

Ваш интерфейс должен моделировать, как вы хотели бы использовать объекты. Поскольку вы пытаетесь абстрагироваться, потребителю не нужно запрашивать БД. Делаете ли вы это свойство или отдельный вызов функции (например, GetPhones()), полностью зависит от вас. Поскольку вы полностью упаковываете вещи, вам придется сделать выбор, насколько глубоко / лениво вы хотите загружать свои объекты.

Другие вопросы по тегам