技术开发 频道

LINQ to SQL公共基类

  好办法,但还不是最好。首先,采用这种方法,我们需要为每个数据实体都定义Detach方法,这过于繁琐。其次,我们不能用这种方法对该逻辑进行抽象。由于在基类中,我们并不知道TEntity的具体类型。此时,我们应该使用反射技术,以下是我的实现:

private void Detach(TEntity entity)
{
    
foreach (FieldInfo fi in entity.GetType().GetFields(BindingFlags.NonPublic |BindingFlags.Instance))
    {
        
if (fi.FieldType.ToString().Contains("EntityRef"))
        {
            var value
= fi.GetValue(entity);
            
if (value != null)
            {
                fi.SetValue(entity,
null);
            }
        }
        
if (fi.FieldType.ToString().Contains("EntitySet"))
        {
            var value
= fi.GetValue(entity);
            
if (value != null)
            {
                MethodInfo mi
= value.GetType().GetMethod("Clear");
                
if (mi != null)
                {
                    mi.Invoke(value,
null);
                }
                fi.SetValue(entity, value);
            }
        }
    }
}


针对EntityRef<T> 字段,可以通过调用FieldInfo的SetValue方法将值赋为null,以此来移除关联。但是,对于EntitySet则不能用同样的方法,因为该字段为集合。如果设置为null,会抛出异常。因此我通过反射调用了该字段的Clear方法,清除集合中的所有元素。最后,我实现的Update方法如下所示:

public void Update(TEntity originalEntity, Action<TEntity> update, bool hasRelationship)
{
    InitDataContext();
    
try
    {
        
if (hasRelationship)
        {
            
//Remove the relationship between the entitis
             Detach(originalEntity);
        }
        m_context.GetTable
<TEntity>().Attach(originalEntity);
        update(originalEntity);
        m_context.SubmitChanges();
    }
    
catch (ChangeConflictException)
    {
        m_context.ChangeConflicts.ResolveAll(RefreshMode.KeepCurrentValues);
        m_context.SubmitChanges();
    }      
}
0
相关文章