上方廣告

Lady Kukki 手作糖霜餅乾

2017年2月24日 星期五

C# 類別屬性複製

近來調整一個Linq to SQL的專案,但由於跟它不是非常熟的狀況下,發生了修改資料後資料庫並無任何反應的情況,實際使用SQL Profiler,發現並沒有執行Update的相關語法。

Google了一下關於Linq to SQL的修改的相關文章看到了這樣的說明【The table could not be updated properly because it had no primary key. (Actually it had the column but the constraint was not copied when I did a SELECT INTO my dev table). The DataContext class requires a primary key for updates.】,但這個並不是這次問題發生的原因。


觀察了一下別人提供的修改資料庫語法(如下參考),資料表類別必須直接透過DataContext讀出後,再針對該物件進行更新,最後SubmitChanges。
OperationDataContext OdContext = new OperationDataContext();

//Get Single course which need to update
COURSE objCourse = OdContext.COURSEs.Single(course => course.course_name == "B.Tech");

//Field which will be update
objCourse.course_desc = "Bachelor of Technology";

// executes the appropriate commands to implement the changes to the database
OdContext.SubmitChanges();

而我的使用方式則是直接從外部傳入一個類別,然後將該類別直接指給查詢出來的類別,最後進行更新(如下參考),但是個要命的錯誤,當從外部傳入參數類別指給查詢出來的類別,實際上這是個傳址的行為,因此原本的DataContent讀出來的實體也就相對的關閉了,因此執行SubmitChanges的時候,就不會再執行SQL的更新了。
public void Update(TB_DATA_Exercise entity)
{
    var dbEntity = DataContextObject.TB_DATA_Exercise.Where(x => x.ID.Equals(entity.ID)).Single();

    dbEntity = entity; //<==要命的錯誤,將要更新的實體內容(entity)指向給直接從DB取出來的實體

    DataContextObject.SubmitChanges();
}

實務上或許有更好的解決辦法,但小弟礙於時程的壓力下,直接使用愚蠢的迂迴方式,將外部類別的屬性Copy(傳值)的方式到DB的類別,最後在更新回資料庫,在此紀錄一下網路上別人分享的複製類別屬性的方法,提供給大家參考。

#建立一個靜態類別方法,提供類別的屬性複製。
public static class Utility
{
    public static void CopyPropertiesTo(this T source, TU dest)
    {
        var sourceProps = typeof(T).GetProperties().Where(x => x.CanRead).ToList();
        var destProps = typeof(TU).GetProperties()
                .Where(x => x.CanWrite)
                .ToList();

        foreach (var sourceProp in sourceProps)
        {
            if (destProps.Any(x => x.Name == sourceProp.Name))
            {
                var p = destProps.First(x => x.Name == sourceProp.Name);
                p.SetValue(dest, sourceProp.GetValue(source, null), null);
            }

        }
    }

#調用方式如下參考。
public void Update(TB_DATA_Exercise entity)
{
    var dbEntity = DataContextObject.TB_DATA_Exercise.Where(x => x.ID.Equals(entity.ID)).Single();
             
    Utility.CopyPropertiesTo(entity, dbEntity); //複製類別屬性

    DataContextObject.SubmitChanges();
}