Note that I dont want my EF model classes to propagate to my domain layer
I have done a workaround. I think it works pretty well
When you want a repository, for example of DbCars, and you insert a new DomainCar you want to get that Id that was only generated when SaveChanges() is applied.
public DomainCar //domain class used in my business layers
{
public int Id{get;set;}
public string Name{get;set;}
}
public DbCar //Car class to be used in the persistence layer
{
public int Id{get;set;}
public string Name{get;set;}
public DateTime CreatedDate{get;set;}
public string CreatedBy{get;set;}
}
First you create a generic IEntity interface and a class implementing it:
public interface IEntity<T>
{
T Id { get; }
}
public class Entity<T> : IEntity<T>
{
dynamic Item { get; }
string PropertyName { get; }
public Entity(dynamic element,string propertyName)
{
Item = element;
PropertyName = propertyName;
}
public T Id
{
get
{
return (T)Item.GetType().GetProperty(PropertyName).GetValue(Item, null);
}
}
}
Then in your add method of the repository you return a IEntity of the type of your Id:
public IEntity<int> AddCar(DomainCar car)
{
var carDb=Mapper.Map<DbCar>(car);//automapper from DomainCar to Car (EF model class)
var insertedItem=context.CARS.Add(carDb);
return new Entity<int>(insertedItem,nameof(carDb.Id));
}
Then , somewhere you are calling the add method and the consequent Save() in the UnitofWork:
using (var unit = UnitOfWorkFactory.Create())
{
IEntity<int> item =unit.CarsRepository.AddCar(new DomainCar ("Ferrari"));
unit.Save(); //this will call internally to context.SaveChanges()
int newId= item.Id; //you can extract the recently generated Id
}