Linq to SQL 通用存储库模式更新问题
本文关键字:模式 更新 新问题 存储 to SQL Linq | 更新日期: 2023-09-27 18:36:40
我有一个奇怪的问题。我正在使用通用存储库模式和Linq to SQL。我在作为dbml生成的对象的对象之间有很多关系,这就是问题所在。我在尝试更新播放器对象时收到错误。当我尝试更新玩家技能名称时发生错误。这是我得到的例外:
System.Data.Linq 中发生类型为"System.InvalidOperationException"的异常.dll但未在用户代码中处理
附加信息:尝试删除技能与玩家技能之间的关系。但是,关系的外键之一 (PlayerSkill.Skill_ID) 不能设置为 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);
}
存储库上的添加或更新方法:
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);
}
}
数据LINQ 层上的更新方法
public void Update(TEntity entity)
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
var original = GetById(GetPrimaryKeyValue(entity));
ApplyChanges(original, entity);
_context.SubmitChanges();
}
最后;应用更改
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();
}
注意:我使用自动映射器来映射对象,但我认为这与错误无关。谢谢。
问题是您的方法ApplyChanges
复制了太多属性。您希望它仅复制标量属性,即 int
、string
等类型的属性,而不是引用和集合。但是你的方法可以做到所有这些。
这会导致 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));
}
}
这将筛选值类型属性和字符串属性(字符串不是值类型,而是类)。