EntityFramework,如何确定哪个dbSet <tentity>与switch / case一起使用?

时间:2017-04-25 11:09:44

标签: c# entity-framework wcf dbset

我是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中的单独函数调用具有完全相同的代码。并且必须多次编写相同的代码集并不是一个很好的解决方案:(

2 个答案:

答案 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,我认为您的类databaseEntitiesDbContext,其中包含您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询问任何类型的商品时,您确定所获得的商品至少包含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打交道。正确的OO设计的唯一原因是,如果你知道你只想调用他们共同的功能,你可以将教师和ClassRoom混合起来就好像它们是相似的。如果是这种情况,请返回界面功能,您可以在其中了解可以调用的常用功能。