2017-04-25 54 views
0

我用的EntityFramework和WCF初學者,所以我還不知道一切是如何工作的,所以我會嘗試是最好的,我可以解釋我的情況..EntityFramework,如何決定使用switch/case的dbSet <TEntity>?

我有一個使用WCF服務用的EntityFramework和我的數據庫已經設法得到它工作得很好,例如是這樣的:當我有一個以上的表,我要決定使用哪一個

using (var entities = new databaseEntities()) 
{ 
    // Check if there is 0 rows, then just add the new row. 
    int count = entities.Table1.Where(i => i.Name == name).Count(); 

    if (count < 1) 
    { 
     var newEntry = new Table1 
     { 
      Name = name, 
      InsertDate = DateTime.Now, 
      CreatedBy = createdBy, 
      Comment = comment, 
      Active = true 
     }; 

     entities.Table1.Add(newEntry); 
     entities.SaveChanges(); 
    } 
} 

問題到達。這些表基本上是相同的,因此會使用相同的操作,所以我想爲它們使用一個函數(這樣我可以避免重複的代碼)。但我似乎無法理解如何我可以在運行時更改表,例如通過開關/外殼。

例如:

// A function that gets the type of the table I want to access 
void WriteToSomeTable(int type) 
{ 
    switch (type) 
    { 
     case 0: 
      //The table to update is Table1 
      break; 
     case 1: 
      //The table to update is Table2 
      break; 
    } 
} 

如果我想獲得所有具有給定名稱的條目的數量與

int count = entities.Table1.Where(i => i.Name == "somename").Count(); 

我怎樣才能使「entities.Table1」確定在運行時? 我可以讓變量:

System.Data.Entity.DbSet<Table1> firstTable = entities.Table1; 
System.Data.Entity.DbSet<Table2> secondTable = entities.Table2; 

所以,我認爲,與列表我可以設置一個int指標;與交換機/箱,然後不同的值,只需使用

int count = list[index].Where(i => i.Name == "somename").Count(); 

,但我不能將它們添加到列表中,因爲它們是不同類型的

// entity.Table1 is 
System.Data.Entity.DbSet<Table1> 
// and entity.Table2 is 
System.Data.Entity.DbSet<Table2> 

的ArrayList不會削減它要麼,因爲如果我嘗試使用ArrayList中的對象,沒有「.Where」函數。我也試過只是System.Data.Entity.Dbset,但要使用「.Where」函數,我需要使用.Cast()函數,但我不能存儲所需的「TEntity」到一個變量(或可以嗎?)。例如:

System.Data.Entity.DbSet firstTable = entity.Table1 
Type t = firstTable.GetType(); 
int count = firstTable.Cast<t>().Where(i => i.Name == "somename").Count();//doesn't work 
//This, however works: 
int count = firstTable.Cast<Table1>().Where(i => i.Name == "somename").Count(); 

我希望我做什麼我在這裏的問題是,從某種意義上說:)希望有人有一個想法,如何解決這個問題,因爲我有這個鬥爭現在的年齡,唯一的解決辦法我已經想出了除了「entity.Table」部分之外,在每個開關/情況下具有完全相同的代碼的單獨函數調用。而不必編寫同一套代碼多次是不是一個很好的解決方案:(

回答

1

讓通用函數......

public void MyAddFunction<T>(T newItem, databaseEntities db, 
      Expression<Func<T, bool>> predicate) where T : class 
    { 
     var table = db.Set<T>(); 

     int count = table.Count(predicate); 

     if(count < 1) 
     { 
      table.Add(newItem); 
     } 

     db.SaveChanges(); 
    } 

,並根據您的情況下調用你的函數(您想添加表1爲例)

using(var entities = new databaseEntities()) 
{ 
    MyAddFunction<Table1>(new Table1(), entities , x => x.Name == "name"); 
} 
+0

真棒!這很簡單,它非常有效!我對泛型函數不太熟悉,所以這甚至沒有想到:)謝謝一堆! – Juuseri

+0

高興地幫助:) – caner

+2

我會使用'任何'而不是'計數'。 –

0

你別這麼說,但既然你與實體框架的工作,我認爲你的databaseEntities類是DbContext是包含您所有的實體作爲DbSet<TEntity>屬性

你寫道你的問題是你知道實體的類型(在我的例子中是TEntity),但是你不知道如何獲得相應的DbSet。請使用switch語句

幸運的是這並不是必需的DbContext.Set(Type)爲您做到了這一點您提供了Type,Dbcontext返回此類型的DbSet。

public class SchoolContext : DbContext 
{ 
    public DbSet<Student> Students {get; set;} 
    public DbSet<Teacher> Teachers {get; set;} 
    public DbSet<ClassRoom> ClassRooms {get; set;} 
    ... 
} 

如果你知道在編譯時已經是類型,使用DbContext.Set<TEntity>,如果TEntity是在運行時才知道,使用DbContext.Set(類型的EntityType)`

Type entityType = ...; 
DbSet mySet = DbContext.Set(entityType); 

問題是當然的,在編譯時你不知道entityType,因此不知道你可以調用哪些函數以及你的entityType具有哪些屬性。

如果您確定您的實體具有某些屬性,例如您的示例屬性Name,請考慮從通用接口派生所有實體。就像這樣:

interface ICommonSchoolProperties 
{ 
    public int Id {get;}   // primary key 
    public string Name {get;} 
} 

public class Teacher : ICommonSchoolProperties {...} 
public class ClassRoom : ICommonSchoolProperties {...} 
etc. 

現在你可以肯定的,每當你問SchoolContext任何類型的項目,你確信你的項目至少有一個IdName。因此,您可以執行以下操作:

Type entityType = ... 
IEnumerable<ICommonSchoolProperties> schoolItems = mySchoolContext 
    .Set(entityType) 
    .Cast<ICommonSchoolProperties>)(); 

而且您可以調用您確定您的SchoolProperty具有的功能。

var nrOfItems = schoolItems 
    .Where(schoolItem => schoolItem.Name = ...) 
    .Count(); 
var allKnownNames = schoolItems 
    .Select(schoolItem => schoolItem.Name) 
    .Distinct(); 

問題仍然存在,如果你想調用教師有的功能,但ClassRooms沒有。

這是一個非常罕見的情況,如果你有一個你不知道它有什麼功能的對象,你應該重新考慮你的設計,並考慮創建處理這些對象的函數,而不是給出類型,解碼哪些功能此對象,然後用它們

相反的:

private void WriteToSomeTable(Type type) 
{ 
    if type is a teacher 
     call teacher functions 
    else if type is classroom 
     call classroomfunctions 
    else 

    DoSomeThingcommon(...) 
} 

考慮:

public void WriteTeacherTable() 
{ 
    call teacher functions(); 
    DoSomethingCommon(); 
} 

private void WriteClassRoomtable() 
{ 
    call classroom functions; 
    DoSomethingCommon(); 
} 

需要注意的是日電線的數量幾乎不增加。

你的程序裏有一個地方,你知道你正在和教師而不是ClassRooms打交道。正確的面向對象設計的唯一原因是,如果你知道你只想調用它們共同的功能,那麼混合教師和ClassRooms就好像它們是類似的東西。如果是這樣的話,回到界面功能,你可以知道你可以調用哪些常用功能。