2017-04-25 4 views
0

私はEntityFrameworkとWCFの初心者ですから、すべての仕組みがわからないので、できる限り私の状況を説明しようとします。EntityFramework、スイッチ/ケースにどの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(); 
    } 
} 

問題が到着しました。テーブルは基本的に同じで、同じ操作を使用するので、それらのすべてに対して1つの関数を使用したいと思います(重複するコードを避けることができます)。しかし、私は理解できないようですどのように私は実行時にスイッチ/ケースを介してテーブルを変更することができます。例については

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

私はどのように私は「entities.Table1」は、実行時に決定することができます

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

で指定された名前を持つすべてのエントリの数を取得したい場合? 私は、変数を作ることができます。

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"を変数(またはI?)たとえば、次のように

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

とあなたのケースに応じては

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

恐ろしい(あなたがたとえばTABLE1を追加したい)あなたの関数を呼び出します!これは簡単で、それはすごくうまくいった!私はあまりにも一般的な関数に精通していなかったので、これも心に来ていない:)おかげで束! – Juuseri

+0

助けてくれると嬉しいです。 – caner

+2

私は 'Count'の代わりに' Any'を使います。 –

0

あなたはEntity Frameworkを使用しているので、私はあなたのクラスdatabaseEntitiesがそのと仮定しています。DbContextDbSet<TEntity>プロパティとしてすべてのエンティティが含まれています

エンティティのタイプを知っていること(私のexaple TEntity内)が問題になりますが、対応するDbSetを取得する方法はわかりません。これにswitch文を使用してください

幸いにもこれは必要ありませんDbContext.Set(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;} 
    ... 
} 

あなたはコンパイル時にすでにタイプを知っている場合TEntityは、実行時にのみ知らされている場合、DbContext.Set<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を混在させる適切なオブジェクト指向設計の唯一の理由は、それらが共通している機能だけを呼び出すことがわかっている場合に似たようなものになります。そのような場合は、呼び出すことができる共通の機能を知っているインタフェース機能に戻ります。

関連する問題