質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Entity Framework

Entity Frameworkは、.NET Framework 3.5より追加されたデータアクセス技術。正式名称は「ADO.NET Entity Framework」です。データベースエンジンに依存しておらず、データプロバイダの変更のみで様々なデータベースに対応できます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

Q&A

解決済

2回答

4681閲覧

C# EntityFrameworkにてテーブル名を動的に運用する方法についての質問です。

Kazu.

総合スコア10

Entity Framework

Entity Frameworkは、.NET Framework 3.5より追加されたデータアクセス技術。正式名称は「ADO.NET Entity Framework」です。データベースエンジンに依存しておらず、データプロバイダの変更のみで様々なデータベースに対応できます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

LINQ

LINQとはLanguage INtegrated Queryの略で、「統合言語クエリ」という意味です。C#やVisual Basicといった言語のコード内に記述することができるクエリです。

0グッド

1クリップ

投稿2019/12/20 03:31

Visual Studio 2019にてEntityFrameWorkで、データベースから読み出す対象の
テーブルを動的に変更できないか?検討をしておりますが、具体的な方法が
よく解りません。以前は、クエリーをString型で作って、テーブル名の部分を
文字列操作で書き換えて、対象テーブルを変更しておりましたが、Linqの
メソッド式で出来ないでしょうか?

以前は、
string queryString00 = "SELECT * FROM TableName ~ "
string query = queryString00.Replace("TableName",Table1);
のような形で実施してました。

これを、EntityFrameWorkのLinqで、例えば下記のような事をしたいのですが、

int TableNo = 1;

var TableName=DbContext.Table0;
switch(TableNo) {
case 1:
TableName = DbContext.Table1;
break;
case 2:
TableName = DbContext.Table2;
break;
}
var query = TableName.Select(o => o.id);

宜しくお願い申し上げます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2019/12/20 03:38 編集

「下記のような事」がそのままできませんか?
Kazu.

2019/12/20 07:32

色々と調べているのですが、出来ない状況です。
Zuishin

2019/12/21 02:11

テーブルが継承関係にないということですね。だとすればそれぞれのカラム名も違うし SQL の使いまわしも無意味になってくると思います。 Database.SqlQuery で直接 SQL を渡して型を使わず受け取るくらいしかないんじゃないでしょうか。
Kazu.

2019/12/23 07:08

ご意見、ありがとうございます。 テーブルの中のカラム名や構成は全く同一のテーブルが10個あります。 ただ、テーブル名が異なります。動的に切り替えたいのですが・・・ テーブルを継承関係にするという事が分かっておりませんので、少し調べてみます。
guest

回答2

0

ベストアンサー

こんにちは。

一応実現できる回答はありますが、正しく動く保証は一切できません。ご了承下さい。
C# と EF の知識がある程度あることを前提にします。


まず、構造が等しい各テーブルの構造のみを抽象クラスとして定義します。

csharp

1public abstract class TableXXModel 2{ 3 public int Id { get; set; } 4 5 public string Name { get; set; } 6}

各テーブルのモデル定義を空にし、先のモデルを継承して定義します。
DbSet<T> の型定義には以下の具体型を使用します。

csharp

1public class Table0 : TableXXModel 2{ 3 // keep empty 4} 5 6public class Table1 : TableXXModel 7{ 8 // keep empty 9} 10 11...

テーブル番号を元に各テーブルを表す DbSet<T> を取得し、Cast メソッドで IQueryable<TableXXModel> にアップキャストし、変数に格納します。

csharp

1var table = TableNo switch 2{ 3 0 => DbContext.Table0.Cast<TableXXModel>(), 4 1 => DbContext.Table1.Cast<TableXXModel>(), 5 2 => DbContext.Table2.Cast<TableXXModel>(), 6 _ => throw ..., 7}; 8

取得した table に対してクエリを書けます。

csharp

1var query = table.Select(o => o.id);

以下は注意です。

アノテーションがどのように作用するかは一切検証していません。
各カラムの注釈は抽象クラスへ、テーブル名は継承クラスへ付ければ動くかもしれませんし、動かないかもしれません。
FluentAPI を使った方が確実です。そうしても正しく動くかは不明です。

奇妙なクエリやパフォーマンス的に問題があるクエリが発行される可能性はあります。
見た限りでは問題なさそうでしたが、まともでないことをしている以上どうなっても不思議ではないです。

今まで自動生成を利用していた場合は、今後は機能しないので手動で全て管理して下さい。

EF はメタプログラミングの塊なので、この方法でちゃんと動いていてもある日突然動かなくなることも考えられます。

同じ構造の複数テーブルを使い分けるというのが謎なので、データベース側を修正して一つのテーブルにまとめることも検討したほうが良いです。
パフォーマンスの観点で水平分割している場合が考えられますが、その場合テーブル名でアクセス先を決めることはしないでしょう。

投稿2019/12/23 10:57

tamoto

総合スコア4103

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Kazu.

2019/12/24 00:02

有難うございます。 この方法で挑戦してみます。ただ、一つのテーブルで運用するのが常識というのも、 理解しました。過去からの枠組みをそのまま使っていますので、そこら辺の解消にも 取り組みたいと思います。 有難うございます。
guest

0

DbContext というのは何なのですか? 実際は DbContext を継承して定義したコンテキストクラスのオブジェクトを指すものですか?

そして、例えば DbContext.Table0 は DbSet<Table0> を返すのでは? 

であれば、DbContext.Table0 ~ DbContext.Table2 はそれぞれ型が違うので、質問に書いてあったようなことはできません。

下のようにエディタレベルでエラーになります。

イメージ説明

投稿2019/12/20 04:50

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Kazu.

2019/12/20 07:31

有難うございます。おっしゃられてますように、DbContextは、実際は DbContext を継承して定義したコンテキストクラスのオブジェクトになります。ですので、ご指摘のように型が違うので、エラーとなってしまします。 Type TableName; case 1: TableName = typeof(DbContext.Table1); break; ver query = DbContext.Set<TableName>(); のような事で、解決出来そうなようにも思うのですが、やはり無理でしょうか??
退会済みユーザー

退会済みユーザー

2019/12/20 07:40

var ではなくて dynamic を使うと少なくともエラーにはなりません。それで質問者さんの目的に沿って使えるかどうかは分かりませんが、そこは考えてください。
Kazu.

2019/12/21 00:14

有難うございます。 上手く行きません。少し考えてみます。
退会済みユーザー

退会済みユーザー

2019/12/21 01:37 編集

どのように使いたいのか書いてもらえると何か代案が出てくるかもしれませんよ。 そもそも、元のコードでも Table0 ~ Table2 の構成を考えなくても使えることは限られてくるはず。そこはどうしてたのですか?
Kazu.

2019/12/23 07:04

Table0~Table2のテーブルの中の構成は同じ内容になっており、記録されているデータが 異なる内容になっております。記録されているデータを表示するプログラムを作りたいのですが、 表示対象によって、参照するテーブルを変更したいと考えております。 従来は、DbContext.Table01.Where といったプロジェクト中にある、Table01の部分をTable02 へ置換して、プログラムを発行して使っていました。あまりスマートではないなと思いまして、 プログラムの頭でTable03など使いたいテーブル名を指定すると、プログラム内で参照するテーブルが 全て、Table03に変わるようにしたいのですが・・・
退会済みユーザー

退会済みユーザー

2019/12/23 11:06 編集

以前は ADO.NET の非接続型アクセスで DataAdapter.Fill(DataTable) のような形で DataTable を作って利用していたのでしょうか。それと似たようなことを Linq to Entities でもやりたいということだと理解しましたが、残念ながら自分には妙案はないです。お役に立てずすみませんが、他の方の回答を期待してください、
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問