Search code examples
c#entity-frameworkwcfdbset

EntityFramework, how to decide which dbSet<TEntity> to use with switch/case?


I'm a beginner with EntityFramework and WCF, so I don't yet know how everything works, so I'll try to explain my situation as best as I can..

I have WCF service that uses a database with EntityFramework and I have managed to get it to work just fine for example like this:

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();
     }
}

The problem arrives when I have more than one table and I want to decide which one to use. The tables are basically the same and thus would use the same operations, so I would like to use one function for all of them (that way I can avoid duplicate code). But I can't seem to understand how I can change the table at runtime for example via a switch/case.

For Example:

// 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;
     }
}

If I want to get the count of all the entries with a given name with

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

how can I make the "entities.Table1" determined at runtime? I can make variables:

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

So I thought that with a list i could set an int index; to a different value with the switch/case and then just use

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

but I can't add them to a List, since they are different types

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

ArrayList won't cut it either, since there are no ".Where" function if i try to use the objects inside the ArrayList.

I also tried with just the System.Data.Entity.Dbset, but to use the ".Where" function, I would need to use .Cast() function, but I cant store the needed "TEntity" to a variable (or can I?). For Example:

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();

I hope I made some sense on what my problem here is :) Hopefully someone has an idea, how to solve this, since I have battled with this for ages now, and the only solution I have come up with is to have a separate function call in each switch/case with the exact same code, except for the "entity.Table" part. And having to write the same set of code multiple times isn't a very good solution :(


Solution

  • Make generic function...

        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();
        }
    

    and according to your cases call your function(You want to add table1 for example)

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