gpt4 book ai didi

c# - Linq to SQL 通用存储库模式更新问题

转载 作者:太空宇宙 更新时间:2023-11-03 15:25:01 26 4
gpt4 key购买 nike

我有一个奇怪的问题。我正在使用通用存储库模式和 Linq to SQL。我在对象之间有很多对多的关系,这些对象是 dbml 生成的对象,这就是问题所在。当我尝试更新 Player 对象时出现错误。当我尝试更新玩家技能名称时发生错误。这是我遇到的异常:

An exception of type 'System.InvalidOperationException' occurred in System.Data.Linq.dll but was not handled in user code

Additional information: An attempt was made to remove a relationship between a Skill and a PlayerSkill. However, one of the relationship's foreign keys (PlayerSkill.Skill_ID) cannot be set to null.

这是更新方法。

 public void Update(PlayerEntity player)
{
Player p = Mapper.Map<PlayerEntity, Player>(player);
_unitOfWork.SkillRepository.AddOrUpdate(p.PlayerSkills.Select(i => i.Skill).ToList());
_unitOfWork.ProfileRepository.AddOrUpdate(p.Profile);
_unitOfWork.SocialAccountRepository.AddOrUpdate(p.SocialAccount);
_unitOfWork.PlayerRepository.AddOrUpdate(p);
}

AddOrUpdate repo 方法:

public void AddOrUpdate(ICollection<TEntity> entities)
{
foreach (var e in entities)
{
AddOrUpdate(e);
}
}

public void AddOrUpdate(TEntity entity)
{
if (GetPrimaryKeyValue(entity) > 0)
{
Update(entity);
}
else
{
Insert(entity);
}
}

DataLINQ层上的Update方法

public void Update(TEntity entity)
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}

var original = GetById(GetPrimaryKeyValue(entity));

ApplyChanges(original, entity);

_context.SubmitChanges();
}

最后; ApplyChanges

private void ApplyChanges<F, S>(F originalEntity, S newEntity)
{
var entityType = typeof(F);
var entityProperties = entityType.GetProperties();
foreach (var propertyInfo in entityProperties)
{
var currentProperty = entityType.GetProperty(propertyInfo.Name);
currentProperty.SetValue(originalEntity, propertyInfo.GetValue(newEntity, null));
}
}

我调用对象如下:

public IHttpActionResult PutPlayer(int id, PlayerEntity player)
{
if (player == null)
{
return NotFound();
}
_playerService.Update(player);

return Ok();
}

注意:我使用AutoMapper来映射对象,但我认为这与错误无关。提前致谢。

最佳答案

问题是您的方法 ApplyChanges 复制了太多属性。您希望它仅复制标量属性,即 intstring 等类型的属性,而不是引用和集合。但是您的方法可以完成所有这些操作。

这会导致 LINQ-to-SQL 断定 PlayerSkills 已被全新的 PlayerSkill 对象集合所取代。所以它会尝试插入新的。但它也会尝试孤立现有的。这会导致 PlayerSkill.Skill_ID 无法设置为 null 的异常。

解决方案是只复制标量属性:

private void ApplyChanges<F, S>(F originalEntity, S newEntity)
{
var entityType = typeof(F);
var entityProperties = entityType.GetProperties();
foreach (var propertyInfo in entityProperties
// Filter scalar properties
.Where(pi => pi.PropertyType.IsValueType || pi.PropertyType == typeof(string)))
{
var currentProperty = entityType.GetProperty(propertyInfo.Name);
currentProperty.SetValue(originalEntity, propertyInfo.GetValue(newEntity, null));
}
}

过滤值类型属性和字符串属性(字符串不是值类型而是类)

关于c# - Linq to SQL 通用存储库模式更新问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35704791/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com