c# - Linq to SQL 中的可配置架构名称?

标签 c# linq-to-sql database-schema

假设我为应用程序的一些简单数据访问生成了一个针对数据库的 Linq to SQL 上下文。该数据库中的表属于特定模式(在本例中,某些表为“CRPDTA”,其他表为“CRPCTL”)。但是,当应用程序投入生产时,相同的表将属于生产数据库中的不同模式(在本例中为“PRODTA”和“PRODCTL”)。

有没有办法让 Linq 2 SQL 的模式名称可配置,在应用程序的配置文件中可以定义?

在数据上下文类中,我看到了表名属性:

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

从技术上讲,我可以直接操作该字符串,但编辑自动生成的文件意味着每次重新生成时都需要重新编辑它。所以我更喜欢更可持续的东西。但到目前为止还没有找到类似的东西。

这是使用此工具无法完成的事情吗?也许有人有在类似情况下行之有效的创造性解决方案?

最佳答案

在 Google 上进行了大量搜索之后,我最终找到了一个有趣的方法 here .这个想法是为 LINQ 实体创建自定义映射源,这只不过是正常功能的传递,直到您到达表名为止。

那篇文章中的确切代码实际上并没有起作用(除了一两个很容易修复的编译错误),因为由于某种原因 TableName 属性实际上没有被调用。所以我必须在 MetaTable 对象中明确设置它。由于这是一个私有(private)领域,因此需要反射(reflection)。

我最终得到的结果如下。

自定义映射源

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

关于c# - Linq to SQL 中的可配置架构名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18519802/

相关文章:

c# - 将gridview转换为itextsharp表并使用asp.net生成pdf

c# - WCF 与托管应用程序通信?

c# - 如何从 LINQ 将 Sql DateTime 设置为 null

sql - 使用 REST API 的 Linq to SQL?

c++ - 如何基于现有文件数据库创建具有模式的内存数据库

sql - 数据库架构 - 用户订阅

mysql - 查找边界框中的所有地理位置

c# - 如何配置 VS 安装程序将文件放入 LocalApplicationData

c# - 按名字/姓氏组合搜索时遇到问题

c# - LINQ Where in 集合子句