2017-04-25 49 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就好像它们是类似的东西。如果是这样的话,回到界面功能,你可以知道你可以调用哪些常用功能。