В настоящее время я использую собственные классы 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.
Надеюсь, это поможет!