특별한 도우미 속성을 가진 클래스와 함께 Dapper.Contrib Update를 사용하십시오.

code-first dapper dapper-contrib sql-update

문제

DapperDapperDapper.Contrib 입니다 Dapper.Contrib . 다음과 같은 클래스가 있으며 데이터베이스에 같은 이름의 테이블이 있습니다.

public class Ware
{        
    public int ID { get; set; }
    public string Name { get; set; }
    public short UnitID { get; set; }
    public short TypeID { get; set; }
    public int CableCodeID { get; set; }
    public string Tag1 { get; set; }
    public string Tag2 { get; set; }
    public bool Discontinued { get; set; }
    public decimal Stock { get; set; } //this is not in database. this is helper
    public string UnitCaption { get; set; } //this is not in database. this is helper
    public string TypeCaption { get; set; } //this is not in database. this is helper
    public string FullCaption //this is not in database. this is helper
    {
        get
        {
            return $"{ID} {Name}";
        }
    }
}

이 클래스의 전체 목록을 데이터베이스로 업데이트해야합니다. 나는 사용한다:

conection.Update(myList); // myList is List<Ware>

하지만 실행하면 오류가 있습니다.

System.Data.SqlClient.SqlException: 'Invalid column name 'Stock'.'
System.Data.SqlClient.SqlException: 'Invalid column name 'UnitCaption'.'
System.Data.SqlClient.SqlException: 'Invalid column name 'TypeCaption'.'
System.Data.SqlClient.SqlException: 'Invalid column name 'FullCaption'.'

이 문제를 해결하는 방법?

수락 된 답변

Dapper.Contrib 소스 코드에서 코드 복사 :

계산 된

    [AttributeUsage(AttributeTargets.Property)]
    public class ComputedAttribute : Attribute { }

계산 된 코드 사용 :

private static List<PropertyInfo> ComputedPropertiesCache(Type type)
{
            IEnumerable<PropertyInfo> pi;
            if (ComputedProperties.TryGetValue(type.TypeHandle, out pi))
            {
                return pi.ToList();
            }

            var computedProperties = TypePropertiesCache(type).Where(p => p.GetCustomAttributes(true).Any(a => a is ComputedAttribute)).ToList();

            ComputedProperties[type.TypeHandle] = computedProperties;
            return computedProperties;
}

이제 Insert<T>Update<T> 에 다음 코드가 있습니다.

var computedProperties = ComputedPropertiesCache(type);

var allPropertiesExceptKeyAndComputed = allProperties.Except(keyProperties.Union(computedProperties)).ToList();

이제 allPropertiesExceptKeyAndComputed 는 코드에서 추가로 처리됩니다.

WriteAttribute

 public class WriteAttribute : Attribute
 {
    public WriteAttribute(bool write)
    {
       Write = write;
    }
    public bool Write { get; }
}

코드에서 IsWriteable 사용 :

 private static List<PropertyInfo> TypePropertiesCache(Type type)
 {
    IEnumerable<PropertyInfo> pis;
    if (TypeProperties.TryGetValue(type.TypeHandle, out pis))
    {
       return pis.ToList();
    }

    var properties = type.GetProperties().Where(IsWriteable).ToArray();
    TypeProperties[type.TypeHandle] = properties;
    return properties.ToList();
 }

 private static bool IsWriteable(PropertyInfo pi)
 {
     var attributes = pi.GetCustomAttributes(typeof(WriteAttribute), false).AsList();
     if (attributes.Count != 1) return true;

     var writeAttribute = (WriteAttribute)attributes[0];
     return writeAttribute.Write;
 }

이제 함수 알 ComputedPropertiesCache 는 메소드 호출 전산화를위한 위에 붙여 TypePropertiesCache , 따라서 무슨 일이 일어날 지, 그것은 (속성을 모두 제외됩니다 Write("false")Computed ), 그러나 Write 속성은 캐시에서 Type 속성을 제외위한 것입니다 이것은 ConcurrentDictionary , Computed 를 사용하여 생성되는데, 이상적으로는 사용 사례를 의미합니다. 예상대로 도움이되기를 바랍니다.



아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow