我是EntityFramework和WCF的初学者,所以我还不知道一切是如何运作的,所以我会尽力解释我的情况......
我有一个使用EntityFramework数据库的WCF服务,我已经设法让它工作正常,例如:
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();
但是我无法将它们添加到List中,因为它们是不同的类型
// 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”部分之外,每个开关/ case中的单独函数调用具有完全相同的代码。并且必须多次编写相同的代码集并不是一个很好的解决方案:(
答案 0 :(得分:3)
制作通用功能......
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();
}
并根据您的情况调用您的函数(例如,您想添加table1)
using(var entities = new databaseEntities())
{
MyAddFunction<Table1>(new Table1(), entities , x => x.Name == "name");
}
答案 1 :(得分:1)
您没有这样说,但是由于您正在使用Entity Framework,我认为您的类databaseEntities
是DbContext
,其中包含您DbSet<TEntity>
属性的所有实体。< / p>
你写的问题是你知道实体的类型(在我的exmple 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(Type 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打交道。正确的OO设计的唯一原因是,如果你知道你只想调用他们共同的功能,你可以将教师和ClassRoom混合起来就好像它们是相似的。如果是这种情况,请返回界面功能,您可以在其中了解可以调用的常用功能。