Рекомендации по проектированию объектов сопоставления Linq to SQL - PullRequest
2 голосов
/ 19 марта 2010

Я надеюсь, что заголовок и следующий текст понятны, я не очень хорошо знаю правильные термины, поэтому, пожалуйста, исправьте меня, если я что-то не так. Я впервые использую 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 ]

2 голосов
/ 19 марта 2010

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

Тогда вы должны предположить, что когда 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);
    }
}
0 голосов
/ 19 марта 2010

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

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

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

0 голосов
/ 19 марта 2010

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

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

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

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

0 голосов
/ 19 марта 2010

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

...