4

アプリケーションの単純なデータ アクセスのために、データベースに対して Linq to SQL コンテキストを生成するとします。そのデータベース内のテーブルは特定のスキーマに属しています (この場合、一部のテーブルは「CRPDTA」、他のテーブルは「CRPCTL」)。ただし、アプリケーションが本番環境に移行すると、同じテーブルが本番データベースの別のスキーマに属します (この場合は「PRODTA」と「PRODCTL」)。

Linq 2 SQL 用にスキーマ名を構成可能にする方法はありますか?アプリケーションの構成ファイルで定義できるものはありますか?

データ コンテキスト クラスには、テーブル名の属性が表示されます。

[global::System.Data.Linq.Mapping.TableAttribute(Name="CRPDTA.TableName")]

技術的には、その文字列を直接操作できますが、自動生成されたファイルを編集すると、再生成されるたびに再編集する必要があります。だから私はもっと持続可能なものを好むでしょう。しかし、これまでのところ、そのようなものを見つけることができませんでした。

これは、このツールではできないことですか? たぶん、誰かが同様の状況でうまくいった創造的な解決策を持っているでしょうか?

4

1 に答える 1

4

Google をいろいろ調べた結果、興味深いアプローチを見つけまし。アイデアは、LINQ エンティティのカスタム マッピング ソースを作成することです。これは、テーブル名のポイントに到達するまで、通常の機能のパススルーにすぎません。

ただし、何らかの理由でTableNameプロパティが実際に呼び出されていないため、その記事の正確なコードは実際には機能していませんでした (1 つまたは 2 つのコンパイル エラーを簡単に修正することは別として)。MetaTableそのため、オブジェクトに明示的に設定する必要がありました。そして、それはプライベート フィールドであるため、これには反映が必要でした。

私が最終的に得たものは次のとおりです。

カスタム マッピング ソース

public class CustomMappingSource : MappingSource
{
    private AttributeMappingSource mapping = new AttributeMappingSource();

    protected override MetaModel CreateModel(Type dataContextType)
    {
        return new CustomMetaModel(mapping.GetModel(dataContextType));
    }
}

これは単なるパススルーであり、ここでは興味深いことは何も起きていません。ただし、次のレベルが必要です。

カスタム メタ モデル

public class CustomMetaModel : MetaModel
{
    private static CustomAttributeMapping mapping = new CustomAttributeMapping();
    private MetaModel model;

    public CustomMetaModel(MetaModel model)
    {
        this.model = model;
    }

    public override Type ContextType
    {
        get { return model.ContextType; }
    }

    public override MappingSource MappingSource
    {
        get { return mapping; }
    }

    public override string DatabaseName
    {
        get { return model.DatabaseName; }
    }

    public override Type ProviderType
    {
        get { return model.ProviderType; }
    }

    public override MetaTable GetTable(Type rowType)
    {
        return new CustomMetaTable(model.GetTable(rowType), model);
    }

    public override IEnumerable<MetaTable> GetTables()
    {
        foreach (var table in model.GetTables())
            yield return new CustomMetaTable(table, model);
    }

    public override MetaFunction GetFunction(System.Reflection.MethodInfo method)
    {
        return model.GetFunction(method);
    }

    public override IEnumerable<MetaFunction> GetFunctions()
    {
        return model.GetFunctions();
    }

    public override MetaType GetMetaType(Type type)
    {
        return model.GetMetaType(type);
    }
}

繰り返しますが、すべてパススルーです。次のレベルに到達するまで、何も興味深いことはありません:

カスタム メタ テーブル

public class CustomMetaTable : MetaTable
{
    private MetaTable table;
    private MetaModel model;

    public CustomMetaTable(MetaTable table, MetaModel model)
    {
        this.table = table;
        this.model = model;

        var tableNameField = this.table.GetType().FindMembers(MemberTypes.Field, BindingFlags.NonPublic | BindingFlags.Instance, (member, criteria) => member.Name == "tableName", null).OfType<FieldInfo>().FirstOrDefault();
        if (tableNameField != null)
            tableNameField.SetValue(this.table, TableName);
    }

    public override System.Reflection.MethodInfo DeleteMethod
    {
        get { return table.DeleteMethod; }
    }

    public override System.Reflection.MethodInfo InsertMethod
    {
        get { return table.InsertMethod; }
    }

    public override System.Reflection.MethodInfo UpdateMethod
    {
        get { return table.UpdateMethod; }
    }

    public override MetaModel Model
    {
        get { return model; }
    }

    public override string TableName
    {
        get
        {
            return table.TableName
                        .Replace("CRPDTA", ConfigurationManager.AppSettings["BusinessDataSchema"])
                        .Replace("CRPCTL", ConfigurationManager.AppSettings["ControlDataSchema"]);
        }
    }

    public override MetaType RowType
    {
        get { return table.RowType; }
    }
}

ここで(半)興味深いことが起こります。このTableNameプロパティは、私が見つけた元の記事 (以前にリンク) に基づいて作成したカスタム プロパティのままです。追加する必要があったのは、テーブルにテーブル名を明示的に設定するためのコンストラクターのリフレクションだけでした。

これで、このカスタム マッピングを使用するようにデータ コンテキストの使用法を設定する必要がありました。

using (var db = new BusinessDBContext(ConfigurationManager.ConnectionStrings["BusinessDBConnectionString"].ConnectionString, new CustomAttributeMapping()))
于 2013-08-29T21:30:32.607 に答える