2016-12-22 72 views
0

我看到了DbSet的各種實現,但我不確定它們是我正在尋找的。使用泛型函數查詢EF5中的DBSet

基本上我們有一堆通過EF5 Code First方法設置的DbSet。我有一個編寫代碼的任務,根據我們在數據庫中已有的記錄來檢查進入API的任何更新/帖子,以確保它們只有在新記錄時才更新/張貼。

顯然我不想爲每個這些DBSet編寫相同的代碼,我想編寫一個類/函數,它將能夠將DbSet作爲參數/參數,然後檢查DBSet作爲記錄。它必須是動態的,因爲它是依賴於最終用戶和他們在做什麼哪個DbSet將需要查詢...

因此,例如,我想要做的事,如呼叫:

CheckDbUniqueRecord(Contracts)其中合同是從表單傳入的合同模型的DbSet。

所以在這個模型中,我們有public class Contract

,並在MainDbContext我們有多個DbSet的其中之一是public DbSet<Contract> Contracts {get; set;}

我希望能夠運行相同的代碼來檢查任何重複記錄的DbSets我們通過簡單地傳遞從該特定的控制器返回的類/模型與該一行功能...

我知道有一種方法來實現這一點,但我不斷收到錯誤消息/類型來自C#的錯誤表明類型不匹配,等等......

任何幫助將不勝感激。

更新:我只會需要此檢查數據庫中的重複記錄,而不是更新。在調用Put函數之前,我將處理客戶端的檢查更新。

我有下面的代碼這是非常近的工作:

public interface getId 
     { 
      int Id { get; set; } 
     } 
     public class Check : getId 
     { 
      public int Id { get; set; } 

      public static bool CheckDBUniqueRecord<T>(T entity) where T : class, getId 
      { 
       MainDbContext db = new MainDbContext(Utility.PortalConnectionString()); 

       var myDbSet = db.Set<T>().ToList(); 

       foreach (var d in myDbSet) 
       { 
        d.Id = 0; 
        if (d == entity) return true; 

       } 
       return false; 


      } 
     } 

通過使用通用約束,但是我得到的方法調用的錯誤:類型XXXX不能用作類型參數「T '在通用方法yyyyyy。沒有從xxxx到yyyy的隱式引用轉換。

這是什麼修復?

+0

所以,換句話說,你想要一個通用的方法來檢查一個任意的實體在數據庫中的存在,對不對?你如何期待檢查完成?你想如何確定哪些字段將被包含在比較中?成員的屬性?除ID之外的所有字段? – DarkSquirrel42

+0

您需要使用泛型方法來啓動,然後在其中使用typeof(T),其中T是類,然後將每種類型抽象爲具體方法,或者您可以使用反射T來嘗試獲取對象屬性和使用它來執行保存更新等,您仍然需要將一些東西傳遞給泛型方法以確定需要創建哪種類型的CRUD。您可以從簡單的單一主鍵對象開始,然後當確信這個工作時,爲更復雜的類型編寫重載方法。 – bilpor

+0

是的,實體將始終存在於數據庫中,所以這不是一個問題。該檢查將針對所有字段運行......基本上,我會遍歷數據庫記錄中的每個字段,並檢查傳入的模型的值。如果所有字段相同,則後/更新將不會運行。發現任何已更改的字段後,它將跳出循環並運行發佈/更新。我實際上只是需要它的職位,因爲我會在運行更新之前檢查客戶端的更新。所以基本上只是爲了確保數據庫中沒有重複的記錄。 – MattE

回答

0

第一件事,第一:這一切只是寫下來的和未經考驗......

的第一件事情很簡單:你的函數簽名......

public static bool CheckDbUniqueRecord<T>(T entity) 

或類似像extensionmethod東西。 ..

public static bool CheckDbUniqueRecord<T>(this DbContext db, T entity) 

基本上你想要做的就是查詢您的DbContext爲對應於你的實體的DbSet ...

var myDbSet = db.Set<T>(); 

現在你需要某種邏輯來找出你想檢查哪些屬性......這可以通過在你的實體類成員上放置屬性來完成......這可以通過檢查所有不是主鍵字段的東西來完成......你必須想出一些東西來告訴你測試哪些東西......爲了簡單起見,我將簡單地介紹一些非常簡單的事情,對於每個屬性都有一個沒有被命名爲「ID」的getter ......根據您的實現,您最有可能想要將這些代碼移動到初始化代碼塊不會每次都運行...

var t = typeof(T); 
var pInfos = t.GetProperties(BindingFlags.Public|BindingFlags.Instance).Where(x=>x.Name!="ID" && x.CanRead).ToArray(); 
Expression exp=null; 
Expression pT = Expression.Parameter(t); 
foreach(var p in pInfos) 
{ 
Expression m = Expression.Property(pT,p); 
Expression c = Expression.Constant(p.GetValue(entity)); 
if(tmp==null) 
{ 
tmp=Expression.Equal(m,c); 
} 
else 
{ 
tmp=Expression.AndAlso(tmp,Expression.Equal(m,c)); 
} 
} 
var myLambda=Expression.Lambda<Func<T,bool>>(tmp,pT); 


return myDbSet.AsQueryable().Any(myLambda); 
+0

我在想因爲我會知道標識符I會搜索DB的MemberId,我會得到記錄,然後我會遍歷每個記錄中的每一列,並將其與 – MattE

+0

記錄中的列進行比較爲什麼你想實現所有與你的memberid匹配的實體?如果你想知道這樣的記錄是否存在,請詢問DBMS ....你想知道什麼會導致類似SELECT count(*)> 0 FROM ... WHERE Property1 ='Value1'AND Property2 ='Value2 '... – DarkSquirrel42