Linq to sql Шаблон репозитория, Некоторые вопросы - PullRequest
3 голосов
/ 09 апреля 2010

Я использую шаблон хранилища с linq to sql, я использую класс хранилища для каждой таблицы. Я хочу знать, хорошо ли я поступаю / стандартно,

ContactRepository

  Contact GetByID()
  Contact GetAll()

COntactTagRepository

 List<ContactTag> Get(long contactID)
 List<ContactTag> GetAll()
 List<ContactTagDetail> GetAllDetails()

class ContactTagDetail
{
  public Contact Contact {get;set;}
  public ContactTag COntactTag {get;set;}
}

Когда мне нужен контакт, я вызываю метод в contactrepository, то же самое для тега контакта

но когда мне нужны контакт и теги вместе, я вызываю GetDetais () в хранилище ContactTag, он не возвращает сущность COntactTag, сгенерированную в orm, и возвращает возвращаемую сущность ContactTagDetail, объединяющую и COntact, и COntactTag, сгенерированный формой, я знаю, что я могу просто вызвать GetAll в репозитории COntactTag и может получить доступ к Contact.ContactTag, но в качестве его linq to sql не будет никакой опции отложенной загрузки на уровне запроса, поэтому всякий раз, когда мне нужен объект со связанным объектом, я создаю класс проекции

Еще одно сомнение - это то, где мне действительно нужно исправить метод, который я могу сделать в репозитории contact & ContactTag, например, в репозитории контактов GetALlWithTags () или что-то еще, но я делаю это в репозитории COntactTag

Какие у вас предложения?

Ответы [ 3 ]

5 голосов
/ 09 апреля 2010

У меня нет времени вдаваться в детали, но в основном у меня нет взаимно-однозначных отношений между таблицами и вашими репозиториями. Я сделал эту ошибку, и она не работает. Вместо этого пусть ваш репозиторий содержит все таблицы, которые связаны концептуально. В вашем случае просто есть хранилище контактов, которое обрабатывает контакты и контакты (и любые другие связанные таблицы). Нет никакого правила относительно того, что означает «связанный», только вы можете решать - но управляйте своим решением, основываясь на понимании того, как элементы вашего приложения естественно сгруппированы вместе.

Также прочитайте эти два потока в SO, которые имеют дело с похожей проблемой:

Несколько или одиночные репозитории с LINQ и Как правильно использовать шаблон репозитория?

1 голос
/ 11 апреля 2010

Это не шаблон репозитория. Шаблон репозитория в основном создает объект, который абстрагируется от постоянства, действуя (концептуально) как совокупность всех объектов определенного типа в домене.

Поэтому хранилище контактов может работать примерно так:

IContacts contacts = GetContactRepository();
using(var uow = UnitOfWork.Create()) {
  var contact1 = contacts.Get(new FindByNameSpecification("Fred"));
  contact1.LastName = "Rubble";
  var contact2 = new Contact("Barney", "Flistone");
  contacts.Add(contact2);
  // both contact1 and contact 2 are implicitly saved at the end of the unit of work
}  

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

IContactRepository contacts = GetContactRepository();
using(var uow = UnitOfWork.Create()) {
  var contact1 = contacts.GetByName("Fred");
  contact1.LastName = "Rubble";
  contacts.Save(contact1);
  var contact2 = new Contact("Barney", "Flistone");
  contacts.Save(contact2);
}  //The save is explicit but the commit is implicit

У вас есть шлюз табличных данных .

Проблема в том, что вы создаете один шлюз для каждой таблицы. Я бы рекомендовал против этого.

Является ли пометка частью вашего контактного домена или нет? Если это так, то вы должны иметь свойства

public class Contact {
  public IEnumerable<Tag> Tags { get; }
  public void TagWith(Tag tag) { .... }
  public void UnTag(Tag tag) { ... }
}

Кроме того, спросите себя, будете ли вы когда-либо добавлять тег с нулевыми контактами под ним? Если нет, тогда это становится еще проще - вам вообще не нужен шлюз для управления тегами, просто позвольте объекту Contact справиться с этим

public interface IContactRepository {
  IEnumerable<Contact> GetAll(); // returns Contacts along with their tags
  void Save(Contact); // saves Contact along with any tags
} 

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

public interface IAssociateTags {
  IEnumerable<Tag> GetTagFor(Contact contact);
  void TagContact(Contact contact, Tag tag);
  void UnTagContact(Contact contact, Tag tag);
}
0 голосов
/ 10 апреля 2010

Я верю, что вы на правильном пути. Одна из проблем, с которой вы столкнетесь при использовании linq to sql, - это сопоставление таблиц один на один. Таким образом, вы вынуждены подвергать вас множеству таблиц отношений.

Я нашел способ обойти это, используя слой данных, который имеет доступ к linq to sql, но отображает все обратно в объекты POCO до возврата вызова.

 public IQueryable<ArtGalleryData.Image> GetImagesByImageGroup(int id)
    {

        return SqlDataContext.Image_ImageGroups
            .Where(iig => iig.ImageGroupID == id)
            .Join(
            SqlDataContext.Images,
            iig => iig.ImageID,
            i => i.ImageID,
            (iig, i) => new ArtGalleryData.Image 
            { ImageID = i.ImageID, 
              Description = i.Description, 
              Title = i.Title, 
              Height = i.Height, 
              Width = i.Width }).AsQueryable();
    }

По сути, я сопоставляю объект linq Image обратно в объект POCO Image. (Я знаю, что это немного грязно, но это лучший пример, который у меня есть.)

Чтобы получить эффект отложенной загрузки, вы должны вернуть объект IQueryable . Это позволит вам задержать выполнение запроса до тех пор, пока вам не потребуется.

Также для объектов с зависимой коллекцией в них я нашел этот замечательный вспомогательный класс: LazyList, который позволяет выполнять отложенную загрузку (отложенное выполнение) коллекций через IQueryable

Большинство того, что я знаю, было из чтения блога Роба Коннериса Магазин MVC .

Прочтите его пост в блоге и скачайте проект магазина, я думаю, он ответит на многие ваши вопросы. Если вы не используете asp.net MVC, то просто посмотрите на его слой доступа к данным, это очень поможет.

Надежда, которая помогает

...