1

linqクラスのテーブルマッピングを動的に設定できるかどうか疑問に思いました。

    [global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.[Comfort 0601$Contact]")]
    public partial class Contact : INotifyPropertyChanging, INotifyPropertyChanged
    {
     ...

これを動的またはプログラムで変更したい理由は、使用しているデータベースがNavisionによって作成されているためです。テーブルには、これらのテーブルが属する会社名のプレフィックスがあります。そのため、そのプレフィックスを変更できるようにしたいと思います。

    [global::System.Data.Linq.Mapping.TableAttribute(Name = "dbo.["+SPResources.Database.Company+"$Contact]")]

聖霊降臨祭の会社として:

    public const string Company = "Comfort 0601";

これを試しましたが、Companyを定数として宣言した場合にのみ機能します。

企業間のテーブル構造は同じです。名前と内容だけが変わります。

誰かがこれについてアドバイスをくれることを願っています。それが可能かどうかもわかりません。

4

4 に答える 4

2

テーブルプレフィックスを追加するための正しい解決策は、SQL Server 2005(またはそれ以降)を使用してから、必要なプレフィックスごとにdb-userを作成し、各db-userのデフォルトスキーマを「dbo」から一意のものに変更することです。

別の解決策は、実行時にMappingSourceを「修正」する機能を使用して既存のDataContextを拡張することです。

[Table]  // Look no name
public class DbRecord
{
    [Column(IsPrimaryKey=true)]
    public long Id { get; set; }
}

CustomDataContext.UpdateCustomTable(typeof(DbRecord), "DbTable");

using (CustomDataContext dc = new CustomDataContext(dbConnection))
{
    Table<DbRecord> dbTable = dc.GetTable<DbRecord>();
    var query = from item in dbTable;
}

これはカスタムDataContextです(既存のテーブル名にプレフィックスを追加するために簡単に変更できると思います)(マルチスレッド環境の場合はDictionaryをConcurrentDictionaryに置き換えます):

public class CustomDataContext : DataContext
{
    static CustomMappingSource _sharedMappingSource = new CustomMappingSource();

    public static void UpdateCustomTable(Type rowType, string tableName)
    {
        _sharedMappingSource.UpdateCustomTable(rowType, tableName);
    }

    public CustomDataContext(System.Data.IDbConnection connection) : base(connection, _sharedMappingSource) { }
    public CustomDataContext(string fileOrServerOrConnection) : base(fileOrServerOrConnection, _sharedMappingSource) { }
}

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

    Dictionary<Type, string> _customTableNames = new Dictionary<Type, string>();

    public void UpdateCustomTable(Type rowType, string tableName)
    {
        if (string.IsNullOrEmpty(tableName))
            throw new ArgumentNullException("TableName");

        _customTableNames[rowType] = tableName;
    }

    protected override MetaModel CreateModel(Type dataContextType)
    {
        MetaModel oldmodel = mapping.GetModel(dataContextType);
        CustomMetaModel newmodel = new CustomMetaModel(oldmodel, _customTableNames);
        return newmodel;
    }
}

internal class CustomMetaModel : MetaModel
{
    MetaModel _orgmodel;

    Dictionary<Type, MetaTable> _customtables = new Dictionary<Type, MetaTable>();
    Dictionary<Type, string> _tableNames = new Dictionary<Type, string>();

    public CustomMetaModel(MetaModel orgmodel, Dictionary<Type, string> tableNames)
    {
        _orgmodel = orgmodel;
        _tableNames = tableNames;
    }

    public override MetaType GetMetaType(Type type)
    {
        MetaTable metaTable;
        if (_customtables.TryGetValue(type, out metaTable))
            return metaTable.RowType;
        else
            return _orgmodel.GetMetaType(type);
    }
    public override MetaTable GetTable(Type rowType)
    {
        MetaTable customMetaTable;
        if (_customtables.TryGetValue(rowType, out customMetaTable))
            return customMetaTable;

        if (_tableNames.ContainsKey(rowType))
        {
            MetaTable orgtable = _orgmodel.GetTable(rowType);
            MetaType orgrowtype = orgtable.RowType;
            CustomMetaType newRowType = new CustomMetaType(orgrowtype, this);
            _customtables.Add(rowType, new CustomMetaTable(orgtable, this, newRowType, _tableNames[rowType]));
            newRowType.MetaTable = _customtables[rowType];
            return newRowType.MetaTable;
        }

        return _orgmodel.GetTable(rowType);
    }

    #region MetaModel Forwards
    public override Type ContextType { get { return _orgmodel.ContextType; } }
    public override string DatabaseName { get { return _orgmodel.DatabaseName; } }
    public override MappingSource MappingSource { get { return _orgmodel.MappingSource; } }
    public override Type ProviderType { get { return _orgmodel.ProviderType; } }
    public override MetaFunction GetFunction(System.Reflection.MethodInfo method) { return _orgmodel.GetFunction(method); }
    public override IEnumerable<MetaFunction> GetFunctions() { return _orgmodel.GetFunctions(); }
    public override IEnumerable<MetaTable> GetTables() { return _orgmodel.GetTables(); }
    #endregion
}

internal class CustomMetaTable : MetaTable
{
    MetaTable _orgtable;
    MetaModel _metamodel;
    MetaType _rowtype;
    string _tableName;

    public CustomMetaTable(MetaTable orgtable, MetaModel metamodel, MetaType rowtype, string tableName)
    {
        _orgtable = orgtable;
        _metamodel = metamodel;
        _rowtype = rowtype;
        _tableName = tableName;
    }

    public override MetaModel Model { get { return _metamodel; } }
    public override MetaType RowType { get { return _rowtype; } }
    public override string TableName { get { return _tableName; } }

    #region MetaTable Forwards
    public override System.Reflection.MethodInfo DeleteMethod { get { return _orgtable.DeleteMethod; } }
    public override System.Reflection.MethodInfo InsertMethod { get { return _orgtable.InsertMethod; } }
    public override System.Reflection.MethodInfo UpdateMethod { get { return _orgtable.UpdateMethod; } }
    #endregion
}

internal class CustomMetaType : MetaType
{
    MetaType _orgtype;
    MetaModel _metamodel;

    public MetaTable MetaTable { get; set; }

    public CustomMetaType(MetaType orgtype, MetaModel metamodel)
    {
        _orgtype = orgtype;
        _metamodel = metamodel;
    }

    public override MetaTable Table { get { return MetaTable; } }
    public override MetaModel Model { get { return _metamodel; } }

    #region MetaType Forwards
    public override System.Collections.ObjectModel.ReadOnlyCollection<MetaAssociation> Associations { get { return _orgtype.Associations; } }
    public override bool CanInstantiate { get { return _orgtype.CanInstantiate; } }
    public override System.Collections.ObjectModel.ReadOnlyCollection<MetaDataMember> DataMembers { get { return _orgtype.DataMembers; } }
    public override MetaDataMember DBGeneratedIdentityMember { get { return _orgtype.DBGeneratedIdentityMember; } }
    public override System.Collections.ObjectModel.ReadOnlyCollection<MetaType> DerivedTypes { get { return _orgtype.DerivedTypes; } }
    public override MetaDataMember Discriminator { get { return _orgtype.Discriminator; } }
    public override bool HasAnyLoadMethod { get { return _orgtype.HasAnyLoadMethod; } }
    public override bool HasAnyValidateMethod { get { return _orgtype.HasAnyValidateMethod; } }
    public override bool HasInheritance { get { return _orgtype.HasInheritance; } }
    public override bool HasInheritanceCode { get { return _orgtype.HasInheritanceCode; } }
    public override bool HasUpdateCheck { get { return _orgtype.HasUpdateCheck; } }
    public override System.Collections.ObjectModel.ReadOnlyCollection<MetaDataMember> IdentityMembers { get { return _orgtype.IdentityMembers; } }
    public override MetaType InheritanceBase { get { return _orgtype.InheritanceBase; } }
    public override object InheritanceCode { get { return _orgtype.InheritanceCode; } }
    public override MetaType InheritanceDefault { get { return _orgtype.InheritanceDefault; } }
    public override MetaType InheritanceRoot { get { return _orgtype.InheritanceRoot; } }
    public override System.Collections.ObjectModel.ReadOnlyCollection<MetaType> InheritanceTypes { get { return _orgtype.InheritanceTypes; } }
    public override bool IsEntity { get { return _orgtype.IsEntity; } }
    public override bool IsInheritanceDefault { get { return _orgtype.IsInheritanceDefault; } }
    public override string Name { get { return _orgtype.Name; } }
    public override System.Reflection.MethodInfo OnLoadedMethod { get { return _orgtype.OnLoadedMethod; } }
    public override System.Reflection.MethodInfo OnValidateMethod { get { return _orgtype.OnValidateMethod; } }
    public override System.Collections.ObjectModel.ReadOnlyCollection<MetaDataMember> PersistentDataMembers { get { return _orgtype.PersistentDataMembers; } }
    public override Type Type { get { return _orgtype.Type; } }
    public override MetaDataMember VersionMember { get { return _orgtype.VersionMember; } }
    public override MetaDataMember GetDataMember(System.Reflection.MemberInfo member) { return _orgtype.GetDataMember(member); }
    public override MetaType GetInheritanceType(Type type) { return _orgtype.GetInheritanceType(type); }
    public override MetaType GetTypeForInheritanceCode(object code) { return _orgtype.GetTypeForInheritanceCode(code); }
    #endregion
}
于 2013-07-30T14:25:39.593 に答える
1

ブライアンとガートの答えは、この問題の可能な解決策です。しかし、実行時にマッピングを変更することは不可能です(ブライアンが述べたように)。

プロジェクトが進行するにつれて、別の会社名が必要な場合(つまり、そのビルドは別の顧客向けである)、プロジェクトを再構築することにしました。この決定により、次の解決策が可能になりました。

VisualStudioによって生成された元のマッピングをコメントアウトしました。

//[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.[Comfort 0601$Contact]")]
    public partial class Contact : INotifyPropertyChanging, INotifyPropertyChanged
    {
    ...

すべてのLinqクラスに独自の部分クラスがあるため、独自のクラスの先頭に変更されたマッピングを追加しました。

[global::System.Data.Linq.Mapping.TableAttribute(Name = "dbo.["+SPResources.Database.Company+"$Contact]")]
public partial class Contact
{

私たちの会社はどこになりますか:

public const string Company = "Comfort 0601";

別の会社で再構築が必要な場合は、Company変数を変更するだけです。

:これは、VSで*.dbmlファイルを変更しない場合にのみ正しく機能します。そうした場合、VSは自動的に変更を元に戻します。

編集:時間が経ち、Entity Frameworkを詳しく調べ始めたとき、この問題に対するより具体的で適切な解決策を見つけました:http: //www.codeproject.com/Articles/421643/How-to-Use-MVC- Net-on-the-Dynamics-NAV-Database-St

于 2013-01-16T11:02:10.207 に答える
0

SQLMetalを使用して、各エンティティのコードをカスタム生成できます。実行時に属性を動的に適用することはできないため、これが最適なオプションです。

于 2013-01-07T13:21:52.080 に答える
0

コードファーストで作業する場合は、流暢なマッピングを使用できます。このToTable()メソッドを使用して、実行時にデータベーステーブルを構成できます(「データベーステーブル名の変更」を参照)。たとえば、OnModelCreating()DbContext派生物のオーバーライド:

string company = "Comfort 0601";
modelBuilder.Entity<Contact>().ToTable(company + "Contact");
modelBuilder.Entity<....
modelBuilder.Entity<....

設定ファイルから会社名を取得できます。

于 2013-01-07T19:37:11.830 に答える