让我们假设有两个组件 - 核心和基础设施。在第一个中有接口和模型。它代表域模型并包含业务逻辑。模型建立在抽象上 - 只使用接口方法。
例如:
public interface INotificationService
{
void Notify(User user, int modelId);
}
public interface IAuthorizationService
{
void IsAuthorized(User user);
}
public interface IPersistenceService
{
int AddSomeEntity(SomeModel model);
void SaveChanges();
}
public interface ISomeModelManagementService
{
void AddSomeModelAndNotify(User user, SomeModel model);
}
public class SomeModelManagementService : ISomeModelManagementService
{
//Here would be constructor injection of INotificationService, IAuthorizationService and IPersistenceService
void AddSomeModelAndNotify(User user, SomeModel model)
{
if(authorizationService.IsAuthorized(user))
{
int id = persistenceService.AddSomeEntity(model);
persistenceService.SaveChanges();
notificationService.Notify(user,id);
}
else
{
throw new UnauthorizedException();
}
}
}
上面的所有代码都将驻留在Core程序集中,并且没有引用接口的实现(ISomeModelManagementService
除外)。
另一方面,在基础架构组件中,将存在基础架构相关问题的实现。例如,负责通过EMailNotificationService
发送电子邮件或通过DbPersistenceService
在数据库中映射和保存核心模型的代码。
我面临的问题是这种方法:
int AddSomeEntity(SomeModel model);
我希望实现批处理SaveChanges
,而不是在每个命令(插入/更新/删除查询)之后立即实现保存实体。问题在于使用Entity Framework插入新实体。 EF将在DbContext上执行SaveChanges
方法后更新其模型并返回主键。
我尝试按参考传递参数,但在SaveChanges
之后没有更新。
可以使用dynamic
返回而不是int来执行此操作,因此insert命令/ add方法将返回数据库模型(不是核心模型),然后可以获取id在SaveChanges
执行之后它,但它是一个肮脏的解决方案。
是否可以通过方法返回对Entity Framework密钥的引用?
执行SaveChanges
后是否有可能更新返回的ID?
int id = persistenceService.AddSomeEntity(model);
persistenceService.SaveChanges();
//Now I'd like to have id updated with the database key value
答案 0 :(得分:0)
一种解决方案可能是返回id的包装器。由于包装器是引用类型,因此应在SaveChanges()
之后更新Id。
// Interface for entities that only contains id.
public interface IIdentifiableEntity
{
int Id { get; }
}
public interface INotificationService
{
void Notify(User user, IIdentifiableEntity entity);
}
public interface IAuthorizationService
{
void IsAuthorized(User user);
}
public interface IPersistenceService
{
// Return the entity as a interface here...
IIdentifiableEntity AddSomeEntity(SomeModel model);
void SaveChanges();
}
public interface ISomeModelManagementService
{
void AddSomeModelAndNotify(User user, SomeModel model);
}
public class SomeModelManagementService : ISomeModelManagementService
{
//Here would be constructor injection of INotificationService, IAuthorizationService and IPersistenceService
void AddSomeModelAndNotify(User user, SomeModel model)
{
if(authorizationService.IsAuthorized(user))
{
IIdentifiableEntity entity = persistenceService.AddSomeEntity(model);
persistenceService.SaveChanges();
// Pass reference entity to Notify.
notificationService.Notify(user,entity);
}
else
{
throw new UnauthorizedException();
}
}
}
然后您的实体必须实现接口IIdentifiableEntity
。我认为这可能是比使用dynamic
更优雅的解决方案。积极的是它是一个非常小的接口,并没有真正暴露实体那么多(除了Id
)。缺点是你的实体离开IPersistenceService的范围,这可能不是你想要的。
示例实现如下:
public class PersistentCustomerService : IPersistenceService
{
public IIdentifiableEntity AddSomeEntity(Customer model)
{
var result = _context.Customers.Add(model);
return result;
}
}
public class Customer : IIdentifiableEntity
{
public int Id {get;set;}
public string Name {get;set;}
}