我在使用EF Codefirst正确保存多对多关系时遇到问题。我已正确建模我的类并使用Fluent-API正确建模连接表。我认为这个问题与使用断开连接的DTO有关。当我将更改保存到父实体(公寓)时,父实体(例如Title和UserId)上的scalular属性保存正确,但对子实体(设施)的更改不会保存到多对多表。
以下是有助于澄清事情的代码流程:
public ICommandResult Execute(CreateOrUpdateCondoCommand command)
{
ICollection<Amenity> amenities = new List<Amenity>();
foreach (var item in command.Amenities)
{
Amenity amenity = new Amenity { AmenityId = item.AmenityId };
amenities.Add(amenity);
}
var condo = new Condo
{
[...other properties]
Title = command.Title,
Amenities = amenities
};
if (condo.CondoId == 0)
{
condoRepository.Add(condo);
}
else
{
condoRepository.Update(condo);
}
unitOfWork.Commit();
return new CommandResult(true);
}
/// <summary>
/// Updates the entity.
/// </summary>
/// <param name="entity">The entity</param>
public virtual void Update(T entity)
{
dbset.Attach(entity);
dataContext.Entry(entity).State = EntityState.Modified;
}
我能够通过创建condoRepository.UpdateCondo(condo)方法来完成工作,如下所示:
/// <summary>
/// Method for updating a condo
/// </summary>
/// <param name="condo">The condo to update</param>
public void UpdateCondo(Condo condo)
{
var updatedCondo = this.DataContext.Set<Condo>().Include("Amenities")
.Single(x => x.CondoId == condo.CondoId);
// Set the attributes
[other properties here...]
updatedCondo.Title = condo.Title;
updatedCondo.Amenities.Clear();
foreach (var amenity in condo.Amenities)
{
var amenityToAttach = this.DataContext.Amenities.Single(x => x.AmenityId == amenity.AmenityId);
updatedCondo.Amenities.Add(amenityToAttach);
}
this.Update(updatedCondo);
}
但是,是否有更好的方法来执行此操作,这是通用的,并且每次我需要保存多对多关系时不需要我创建自定义“更新”方法?这个https://stackoverflow.com/a/11169307/3221076答案有助于澄清我认为问题所在,但我不确定如何实施更通用的方法。
谢谢, 杰森
答案 0 :(得分:0)
尝试使用本教程,希望对您有所帮助。
答案 1 :(得分:-1)
我不知道如何使它完全通用,但我做了类似的事情,它允许你添加,删除和修改主 - 细节关系。 (我认为最初的想法来自史蒂文桑德森,但我找不到它。)这段代码在我的DbContext中。希望它有所帮助。
public Condo UpdateSheet(Condo condo) {
Guard.IsNotNull(condo);
List<long> retainedAmenityIds = (from amenity in condo.Amenities
where amenity.Id != 0
select amenity.Id).ToList();
List<Amenity> retainedAmenities = (from amenity in condo.Amenities
where amenity.Id != 0
select amenity).ToList();
string sql = String.Format("SELECT Id FROM {0} WHERE CondoId = {1}", GetTableName<Amenity>(), condo.Id);
List<long> deletedAmenityIds = Database.SqlQuery<long>(sql).Except(retainedAmenityIds).ToList();
if (0 < deletedAmenityIds.Count) {
foreach (var id in deletedAmenityIds) {
Amenity amenity = Amenities.Single(a => a.Id == id);
Amenities.Remove(amenity);
}
}
List<Amenity> addedAmenities = condo.Amenities.Except(retainedAmenities).ToList();
foreach (var amenity in addedAmenities) {
amenity.SheetId = condo.Id;
Entry(amenity).State = EntityState.Added;
}
foreach (var amenity in retainedAmenities) { Entry(amenity).State = EntityState.Modified; }
Entry(condo).State = EntityState.Modified;
SaveChanges();
return condo;
}