EntityFramework,如何决定使用switch/case的dbSet ?
我用的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”部分之外,在每个开关/情况下具有完全相同的代码的单独函数调用。而不必编写同一套代码多次是不是一个很好的解决方案:(
让通用函数......
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");
}
你别这么说,但既然你与实体框架的工作,我认为你的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
任何类型的项目,你确信你的项目至少有一个Id
和Name
。因此,您可以执行以下操作:
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就好像它们是类似的东西。如果是这样的话,回到界面功能,你可以知道你可以调用哪些常用功能。
真棒!这很简单,它非常有效!我对泛型函数不太熟悉,所以这甚至没有想到:)谢谢一堆! – Juuseri
高兴地帮助:) – caner
我会使用'任何'而不是'计数'。 –