Я уже некоторое время борюсь с проблемой, для которой я не могу найти лучшее решение.
Это первый проект, в котором я хочу использовать шаблон проектирования, управляемый доменом, на самом деле это просто демонстрация проект, который я использую, чтобы улучшить свои навыки кодирования.
Мой проект (настольное приложение WPF) довольно прост и просто сохраняет проекты в базе данных. Каждый проект может иметь несколько пробелов (1: n). Все первичные ключи генерируются базой данных. Поэтому я создал простую модель постоянства:
public class Project
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Owner { get; set; }
public DateTime CreationDate { get; set; }
public ICollection<Space> Spaces { get; set; }
}
public class Space
{
public int Id { get; set; }
public string Name { get; set; }
public int ProjectId { get; set; }
public Project Project { get; set; }
}
Я также создаю модель предметной области, которая будет содержать некоторые бизнес-логики c, сейчас она просто выглядит как модель постоянства.
public interface IIdentifiable
{
public int Id { get; }
}
public class Project : IIdentifiable
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Owner { get; set; }
public DateTime CreationDate { get; set; }
public ICollection<Space> Spaces { get; set; } = new List<Space>();
}
public class Space : IIdentifiable
{
public int Id { get; set; }
public string Name { get; set; }
public Project Project { get; set; }
}
После этого я создал службу «хранения», в которой будут методы для добавления / обновления / удаления сущностей.
Я разработал службу, которая принимает модели предметной области и преобразует их в модели постоянства (используя automapper). Я хочу иметь возможность добавлять / обновлять / удалять сущности без немедленного сохранения изменений.
Поэтому я создал абстрактный класс, который предоставляет мне все эти функции для каждого типа домена.
public class MyDbSet<TEntity, TDomain> where TEntity : class
where TDomain : class, IIdentifiable
{
protected readonly RemotingContext _context;
protected readonly IMapper _mapper;
protected readonly DbSet<TEntity> _entities;
public RemotingSet(RemotingContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
_entities = _context.Set<TEntity>();
}
public void AddAsync(TDomain item)
{
var entity = _mapper.Map<TEntity>(item);
_entities.Add(entity);
}
public async Task Update(TDomain item)
{
var entity = await _entities.FindAsync(item.Id);
if (entity != null)
_mapper.Map(item, entity);
}
public async Task<bool> TryRemove(TDomain item)
{
var entity = await _entities.FindAsync(item.Id);
if (entity != null)
{
_entities.Remove(entity);
return true;
}
return false;
}
}
и наконец, мой класс хранения, который содержит MySet для каждого типа модели домена:
public class Storage:IDisposable
{
private readonly IMapper _mapper;
private readonly MyContext _context;
public Projects Projects { get; private set; }
public Spaces Spaces { get; private set; }
public Storage()
{
_context = new MyContext();
_mapper = new MapperConfiguration(cfg => cfg.AddProfile(new Config.RemotingProfile())).CreateMapper();
Projects = new Projects(_context, _mapper);
Spaces = new Spaces(_context, _mapper);
}
public Task<int> SaveChanges()
{
return _context.SaveChangesAsync();
}
public void Dispose()
{
_context.Dispose();
}
}
public class Projects : MySet<Persistence.Models.Project, Domain.Models.Project>
{
public Projects(MyContext context, IMapper mapper) : base(context, mapper) { }
public async Task<IEnumerable<Project>> Get()
{
return _mapper.Map<IEnumerable<Project>>(await _context.dbsProjects.Include(p => p.Spaces).ToListAsync());
}
}
public class Spaces : MySet<Persistence.Models.Space, Domain.Models.Space>
{
public Spaces(MyContext context, IMapper mapper) : base(context, mapper) { }
}
Моя конфигурация Automapper выглядит следующим образом:
public class MyProfile : Profile
{
public MyProfile()
{
CreateMap<Persistence.Models.Project, Domain.Models.Project>().ReverseMap();
CreateMap<Persistence.Models.Space, Domain.Models.Space>().ReverseMap();
}
}
Итак, теперь моя проблема: как упоминалось выше, сохранение базы данных будет сделано не сразу, а когда пользователь захочет. Означает, что когда я добавляю проект и впоследствии обновляю его (например, изменяю имя), этот метод обновления не найдет проект, так как у него пока нет установленного идентификатора, поскольку save не был вызван.
Если я позвоню сохранить после добавления, а затем обновить проект, все работает как положено.
Мой вопрос: как я могу использовать Entity Framework и его поведение отслеживания изменений в таком сценарии? Я не знаю, правильно ли я иду в реализации такого дизайна.
Буду очень признателен за вашу помощь в этом. Как уже говорилось, я впервые пытаюсь реализовать такой дизайн, поэтому, если мой подход совершенно неправильный, я также буду рад получить совет о том, как сделать это правильно.
Мануэль