Entity Framework / Linq to sql модель для бизнес-модели - PullRequest
1 голос
/ 28 марта 2011

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

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

В одном из моих последних проектов использовались DDD и структура сущностей.При необходимости обновления объекта он перемещал бизнес-объект на уровень репозитория, который при переходе на уровень DAL создавал контекст и затем запрашивал объект.Это обновило бы значения и повторно скопировало.

Я не увидел большой точки, поскольку контекст данных не был сохранен, и потребовался дополнительный запрос, чтобы получить объект перед обновлением.Обычно я просто делаю обновление (если параллелизм не был проблемой)

Поэтому мои вопросы сводятся к:

  1. Имеет ли смысл разделять сгенерированные классы linq на sql вБизнес-объекты?
  2. Должен ли контекст данных быть сохранен или это непрактично?

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

1 Ответ

3 голосов
/ 28 марта 2011

В настоящее время я использую собственные классы Dto и Datacontext вместо использования автоматически сгенерированных файлов кода из Linq в Sql. Чтобы дать некоторое представление о моей архитектуре / моделировании решения, у меня есть проект "Контракт" и проект "Dal". (Также проект «Модель», но я постараюсь сосредоточиться здесь только на Дале). Скручивая вручную мои собственные Dtos и Datacontext, делая все намного меньше и проще, я приведу несколько примеров того, как я это делаю здесь.

Я никогда не возвращаю объект Dto за пределы Dal, фактически я объявляю их внутренними. Я возвращаю их в виде интерфейса (интерфейсы расположены на уровне «Контракт»). Мы сделаем простой «PersonRepository», который реализует интерфейсы «IPersonRetriever и IPersonSaver».

Контракты:

public interface IPersonRetriever
{
     IPerson GetPersonById(Guid personId);
}

public interface IPersonSaver
{
     void SavePerson(IPerson person);
}

Dal:

    public class PersonRepository : IPersonSaver, IPersonRetriever
    {
        private string _connectionString;

        public PersonRepository(string connectionString)
        {
            _connectionString = connectionString;
        }

        IPerson IPersonRetriever.GetPersonById(Guid id)
        {
            using (var dc = new PersonDataContext(_connectionString))
            {
                return dc.PersonDtos.FirstOrDefault(p => p.PersonId == id);
            }
        }

        void IPersonSaver.SavePerson(IPerson person)
        {
            using (var dc = new PersonDataContext(_connectionString))
            {
                var personDto = new PersonDto
                {
                    Id = person.Id,
                    FirstName = person.FirstName,
                    Age = person.Age
                };

                dc.PersonDtos.InsertOnSubmit(personDto);
                dc.SubmitChanges();
            }
        }
    }

PersonDataContext:

    internal class PersonDataContext : System.Data.Linq.DataContext
    {
        static MappingSource _mappingSource = new AttributeMappingSource(); // necessary for pre-compiled linq queries in .Net 4.0+

        internal PersonDataContext(string connectionString) : base(connectionString, _mappingSource) { }

        internal Table<PersonDto> PersonDtos { get { return GetTable<PersonDto>(); } }
    }

    [Table(Name = "dbo.Persons")]
    internal class PersonDto : IPerson
    {
        [Column(Name = "PersonIdentityId", IsPrimaryKey = true, IsDbGenerated = false)]
        internal Guid Id { get; set; }

        [Column]
        internal string FirstName { get; set; }

        [Column]
        internal int Age { get; set; }

        #region IPerson implementation

        Guid IPerson.Id { get { return this.Id; } }
        string IPerson.FirstName { get { return this.FirstName; } }
        int IPerson.Age { get { return this.Age; } }

        #endregion
    }

Вам нужно будет добавить атрибут «Столбец» ко всем вашим свойствам Dto, но если вы заметите, есть ли однозначная корреляция между тем, что вы хотите, чтобы поле отображалось как на интерфейсе, и имя фактического столбца таблицы, вам не нужно добавлять какие-либо из именованных параметров. В этом примере мой PersonId в базе данных хранится как «PersonIdentityId», но я только хочу, чтобы в моем интерфейсе было поле с надписью «Id».

Вот как я делаю свой слой Даля, я считаю, что этот слой должен быть тупым, настоящим тупым. Тупой в том смысле, что он существует только для CRUD (Create, Retrieve, Update и Delete) операций. Вся бизнес-логика будет включена в мой «модельный» проект, который будет использовать и использовать интерфейсы IPersonSaver и IPersonRetriever.

Надеюсь, это поможет!

...