Советы по проектированию объектов сопоставления Linq to SQL

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

Вопрос

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

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

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

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

Это было полезно?

Решение

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

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

Другие советы

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top