Объекты C #, интерфейсы и база данных

Как лучше всего писать в базу данных при работе с объектами и интерфейсами? Существует множество мнений относительно объектного дизайна, но я не понимаю, что такое база данных. Простой пример:

Предположим, что базовый класс Contact содержит общие поля, такие как имя контакта (Билл, Фред, Салли) и местоположение (дом, работа и т. Д.). Добавьте интерфейс IPhone (код города, номер телефона, добавочный номер) и интерфейс IEmail (адрес электронной почты, копия), чтобы абстрагироваться от различий. Затем создайте классы (Телефон, Электронная почта), которые наследуются от них следующим образом:

    Phone: Contact, IPhone 
    Email: Contact, IEMail

Альтернативой было бы создание интерфейса IContact вместо базового класса Contact следующим образом:

    Phone: IContact, IPhone
    Email: IContact, IEMail

Если не реализовывать NHibernate или Entity Framework, что лучше всего использовать для кода доступа к данным, если эти объекты записываются в одну таблицу базы данных? То, что я увидел, кажется довольно неуклюжим.


person user50622    schedule 01.01.2009    source источник
comment
Что делать, если у контакта есть телефон и электронная почта? Контакт должен иметь поле "Телефон", содержащее все данные о телефоне, и поле "Электронная почта", содержащее все данные электронной почты. Возможно, вы даже захотите иметь несколько телефонов или адресов электронной почты; но телефон не является контактом, так почему же класс Phone расширяет контакт?   -  person configurator    schedule 01.01.2009


Ответы (5)


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

Как только у меня это получится, я использую DAL, способный отражать эти классы и генерировать требуемый SQL на лету; после профилирования мне, возможно, придется создать несколько SP, но его результаты также отправляются принимающему DTO.

Причин для использования интерфейсов я пока не обнаружил.

person Otávio Décio    schedule 01.01.2009
comment
Серверные интерфейсы играют отличную роль в DAL. Вы можете подумать о том, чтобы связать все свои объектные службы и ссылаться на них по ссылке на интерфейс. Это упростит создание макета, и если вам понадобится масштабировать или удаленно позже, вам будет намного проще это сделать. - person Jason Jackson; 01.01.2009
comment
Это правда, я не думал о насмешках и удалении. - person Otávio Décio; 01.01.2009

Думаю, вам нужно рассмотреть отношения между этими тремя сущностями. Произнесите вслух следующие утверждения и посмотрите, какое из них подходит для вашего приложения:

  • Phone IS A Contact
  • Phone ЕСТЬ A Contact

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

Однако вас интересует доступ к данным, и вы упомянули, что существует одна таблица базы данных, что заставляет меня задаться вопросом, зачем вам нужны отдельные сущности для Contact, Phone и Email. Я бы порекомендовал вам либо реорганизовать свой код, чтобы включить единый объект для представления вашей модели данных, поскольку это снизит сложность вашей кодовой базы, либо провести рефакторинг вашей схемы базы данных, чтобы отразить то, что, похоже, вы действительно хотите (на основе вашего образца кода).

person Andrew Hare    schedule 01.01.2009
comment
На самом деле, я бы подумал об этом иначе: у контакта есть телефон. - person tvanfosson; 01.01.2009
comment
Это то, о чем я думал сначала, но его модель данных, похоже, наоборот. - person Andrew Hare; 01.01.2009

Сначала создайте свою базу данных, чтобы быть уверенным, что вы действительно сможете хранить все, что вам нужно. Затем создайте общие запросы, такие как «Все клиенты и их основной номер телефона» и «Один клиент со всеми их номерами телефонов».

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

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

person Jonathan Allen    schedule 01.01.2009

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

Contacts Table
     ContactID
     FirstName
     LastName
     MI
     StreetAddress1
     StreetAddress2
     City
     StateProvince
     PostalCode
     PreferredContactMethod (0 = Phone, 1 = Email)
     ... more details ...

PhoneNumbers Table
     PhoneID
     ContactID
     PhoneNumber
     IsPrimary
     ...more details...

EmailAddresses Table
     EmailID
     ContactID
     EmailAddress
     IsPrimary
     ...more details...

Тогда для ваших классов у вас будет класс Contact, который содержит один или несколько номеров телефона и один или несколько адресов электронной почты. Если у вас есть другие вещи, кроме контактов, у которых есть номера телефонов или адреса электронной почты, тогда может иметь смысл иметь интерфейсы, указывающие, что они являются IPhoneable или IEmailable - это означает, что вы просто можете добавлять / удалять из них номера телефонов или адреса электронной почты, например :

public interface IPhoneable
{
     public PhoneNumber GetPrimaryNumber();
     public void AddNumber( PhoneNUmber number );
     public IEnumerable<PhoneNumber> GetNumbers();
}

public interface IEmailable
{
     public EmailAddress GetPrimaryAddress();
     public void AddEmailAddress( EmailAddress address );
     public IEnumerable<EmailAddress> GetEmailAddresses();
}

public class Contact : IPhoneable, IEmailable
{
     private List<PhoneNumber> phoneNumbers;
     private List<EmailAddresses> emailAddresses;

     public int ContactID { get; private set; }
     public string FirstName { get; set; }
     ...

     public Contact()
     {
         this.phoneNumbers = new List<PhoneNumber>();
         this.emailAddresses = new List<EmailAddress>();
     }

     public PhoneNumber GetPrimaryNumber()
     {
          foreach (PhoneNumber number in this.phoneNumbers)
          {
               if (number.IsPrimary)
               {
                    return number;
               }
          }
          return null;
      }

      ...
}

При желании вы могли бы иметь PhoneableContact и EmailableContact, которые были бы разделены на подклассы Contact и были бы дифференцированными в зависимости от предпочтительного метода связи, но я действительно не вижу в этом необходимости. Если бы вы это сделали, Contact не реализовал бы ни один из интерфейсов - подклассы реализовали бы соответствующие интерфейсы соответственно.

person tvanfosson    schedule 01.01.2009

В этом случае ... я думаю, что лучший вариант - использовать объект базы данных, например DB4O.

«Db4o - это объектная база данных с открытым исходным кодом, которая позволяет разработчикам Java и .NET сохранять и извлекать любой объект приложения, включая тематические карты, с помощью только одной строчки кода, устраняя необходимость предварительно определять или поддерживать отдельную жесткую модель данных».

http://www.db4o.com/

person Pedro Luz    schedule 01.01.2009