我在EF4 CTP5项目中使用POCO类,我在删除子属性时遇到问题。这是我的例子(希望不会太久)。
旅游类的相关部分
public partial class Tour
{
public Guid TourId { get; private set; }
protected virtual List<Agent> _agents { get; set; }
public void AddAgent(Agent agent)
{
_agents.Add(agent);
}
public void RemoveAgent(Guid agentId)
{
var a = Agents.Single(x => x.AgentId == agentId);
_agents.Remove(Agents.Single(x => x.AgentId == agentId));
}
}
命令处理程序
public class DeleteAgentCommandHandler : ICommandHandler<DeleteAgentCommand>
{
private readonly IRepository<Core.Domain.Tour> _repository;
private readonly IUnitOfWork _unitOfWork;
public DeleteAgentCommandHandler(
IRepository<Core.Domain.Tour> repository,
IUnitOfWork unitOfWork
)
{
_repository = repository;
_unitOfWork = unitOfWork;
}
public void Receive(DeleteAgentCommand command)
{
var tour = _repository.GetById(command.TourId);
tour.RemoveAgent(command.AgentId);
// The following line just ends up calling
// DbContext.SaveChanges(); on the current context.
_unitOfWork.Commit();
}
}
以下是我的UnitOfWork调用DbContext.SaveChanges()
操作失败:无法更改关系,因为一个或多个外键属性不可为空。当对关系进行更改时,相关的外键属性将设置为空值。如果外键不支持空值,则必须定义新关系,必须为foreign-key属性分配另一个非空值,或者必须删除不相关的对象。
这种情况正在发生,因为EF不会仅仅因为它已从我的Tour类中的Agents集合中删除而自动从数据库中删除了Agent实体。
我需要显式调用dbContext.Agents.DeleteObject(a);
,但我的问题是,我无法从我的POCO中访问dbContext。
有没有办法处理这种情况?
答案 0 :(得分:1)
使用您当前的体系结构,我担心您需要向DeleteAgentCommandHandler
提供第二个存储库(我猜是IRepository<Core.Domain.Agent>
),然后在第二个存储库中调用类似Delete(command.AgentId)
的内容。< / p>
或者您可以将IUnitOfWork
扩展为存储库的工厂,因此接口将获得一个额外的方法,如T CreateRepository<T>()
,它允许您从工作单元中提取通用存储库的任何实例。 (那么你只需要将IUnitOfWork
注入DeleteAgentCommandHandler
,而不是注册库。)
或远离业务/ UI层中的通用存储库。如果Agent
完全依赖于Tour
,则根本不需要存储库。非通用ITourRepository
可以有方法来处理从数据库层中的游览中删除代理的情况。
答案 1 :(得分:0)
这似乎应该有用。我发现这篇文章表明正在调查此功能的未来版本:
http://social.msdn.microsoft.com/Forums/en-US/adonetefx/thread/58a31f34-9d2c-498d-aff3-fc96988a3ddc/
我还发现了另一篇帖子(某个地方 - 不幸的是我丢失了它),建议在DbContext OnModelCreating方法中将父实体的密钥添加到子实体,如下所示:
modelBuilder.Entity<Agent>()
.HasKey(AgentId)
.HasKey(TourId);
目前,这会在运行时使用代码优先抛出异常,尽管我在使用EDMX文件时通过黑客攻击XAML以在存储数据模型中包含父键以及概念数据模型来实现此功能。我认为这种行为差异是因为在EDMX文件的情况下,EF信任它保存的商店元数据是准确的,而代码优先检查数据库以查看它的模型是否匹配。
虽然我尚未尝试过,但可能有效的另一种方法是将父键作为复合键包含在子表中,以便代码优先。显然,更改数据库或黑客攻击XAML都不是理想的,也是最好的解决方法。