c# Entity Framework EF 4.1 在运行时更改架构和数据库名称

标签 c# database oracle entity-framework-4 schema

我搜索了一些主题,但没有找到解决我问题的具体方法。

我的应用是一个 C# 商业应用。我首先使用 EF 4.1 数据库。我从开发数据库连接生成模型并创建一个 Model.edmx 文件和所有 EF 的东西都很好。

我的目标是向客户交付一个应用程序,让他自己自由创建数据库和数据库用户。做吧,在运行时我会得到用户名、密码、数据库连接和模式名称参数来连接到客户数据库。这样,要部署应用程序,我只需要让客户创建一个数据库并将数据库参数添加到应用程序配置文件中即可。

所以,我的目标是在运行时更改连接字符串和架构参数,而不更改所有自动生成的 edmx 文件,不触及 VS 生成的代码。

我环顾四周,发现:

对于 EF 早期版本:

Changing schema name on runtime - Entity Framework

http://efmodeladapter.codeplex.com

所有其他帖子都围绕着那个。我什至尝试使用第一个邮政编码,但没有成功。

但我看到 EF 4.1 带有更好的支持工具来执行此操作,但我找不到它的引用或示例。重要的是不要更改 VS 自动生成的代码。

我是 EF 的新手,所以我想寻求帮助以完成以下任务: a) 在运行时更改连接字符串,添加我的用户名、密码和数据库服务器/端口参数 b) 更改数据库架构

我使用 Oracle 作为数据库服务器(这让事情变得更糟,因为 Oracle 将模式和用户混合在一起)。

最佳答案

其实,我也需要解决这个问题。我很快提出了解决方案,效果很好。我在 Internet 上找不到太多关于此的信息,所以我不确定“EF 4.1 带有更好的支持工具来做到这一点”。

具体示例“在运行时更改架构名称 - Entity Framework ”并不完全适合我,但是通过一些小的修改我就可以使用了。

这是一个可以做到这一点的 DatabaseUtils 类:

internal static class DatabaseUtils
{
    /// <summary>
    /// Builds the connection string for Entity framework.
    /// </summary>
    /// <returns></returns>
    public static EntityConnection BuildConnection(BuildConnectionParams buildConnectionParams)
    {
        var sqlBuilder = new SqlConnectionStringBuilder
            {
                DataSource = buildConnectionParams.ServerName,
                InitialCatalog = buildConnectionParams.DatabaseName,
                IntegratedSecurity = true
            };

        var providerString = sqlBuilder.ToString();
        var entityBuilder = new EntityConnectionStringBuilder
        {
            Provider = buildConnectionParams.ProviderName,
            ProviderConnectionString = providerString,
            Metadata = string.Format(@"res://*/{0}.csdl|
                        res://*/{0}.ssdl|
                        res://*/{0}.msl", buildConnectionParams.ModelName)
        };

        return CreateConnection(buildConnectionParams.SchemaName, entityBuilder, buildConnectionParams.ModelName);
    }


    /// <summary>
    /// Creates the EntityConnection, based on new schema & existing connectionString
    /// </summary>
    /// <param name="schemaName">Name of the schema.</param>
    /// <param name="connectionBuilder"></param>
    /// <param name="modelName">Name of the model.</param>
    /// <returns></returns>
    private static EntityConnection CreateConnection(string schemaName, EntityConnectionStringBuilder connectionBuilder, string modelName)
    {
        Func<string, Stream> generateStream =
            extension => Assembly.GetExecutingAssembly().GetManifestResourceStream(string.Concat(modelName, extension));

        Action<IEnumerable<Stream>> disposeCollection = streams =>
        {
            if (streams == null)
                return;

            foreach (var stream in streams.Where(stream => stream != null))
                stream.Dispose();
        };

        var conceptualReader = generateStream(".csdl");
        var mappingReader = generateStream(".msl");
        var storageReader = generateStream(".ssdl");

        if (conceptualReader == null || mappingReader == null || storageReader == null)
        {
            disposeCollection(new[] { conceptualReader, mappingReader, storageReader });
            return null;
        }

        var storageXml = XElement.Load(storageReader);

        foreach (var entitySet in storageXml.Descendants())
        {
            var schemaAttribute = entitySet.Attributes("Schema").FirstOrDefault();
            if (schemaAttribute != null)
                schemaAttribute.SetValue(schemaName);
        }

        storageXml.CreateReader();

        var workspace = new MetadataWorkspace();

        var storageCollection = new StoreItemCollection(new[] { storageXml.CreateReader() });
        var conceptualCollection = new EdmItemCollection(new[] { XmlReader.Create(conceptualReader) });
        var mappingCollection = new StorageMappingItemCollection(conceptualCollection, 
                                                                storageCollection,
                                                                new[] { XmlReader.Create(mappingReader) });

        workspace.RegisterItemCollection(conceptualCollection);
        workspace.RegisterItemCollection(storageCollection);
        workspace.RegisterItemCollection(mappingCollection);

        var connection = DbProviderFactories.GetFactory(connectionBuilder.Provider).CreateConnection();
        if (connection == null)
        {
            disposeCollection(new[] { conceptualReader, mappingReader, storageReader });
            return null;
        }

        connection.ConnectionString = connectionBuilder.ProviderConnectionString;
        return new EntityConnection(workspace, connection);
    }
}

用法:

/// <summary>
/// Initializes a new instance of the <see cref="DynamicAQDContext"/> class.
/// </summary>
public DynamicAQDContext()
{
    var entityConnection = DatabaseUtils.BuildConnection(new BuildConnectionParams
    {
        ProviderName = "System.Data.SqlClient",
        ServerName = "localhost\\",
        DatabaseName = "",
        ModelName = "YOURMODEL",
        SchemaName = "SCHEMA"
    });

    if(entityConnection == null)
        throw new Exception("Can't create EntityConnection");

    _entities = new LINKEntities(entityConnection);
}

更多信息可以在这里找到:http://bestplayah.com/entity-framework-dynamic-schema-changes-using-database-first-approach/

关于c# Entity Framework EF 4.1 在运行时更改架构和数据库名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18532901/

相关文章:

c# - Rx.Net 消息解析器

python - Django 树表的复杂分区和排序

database - 函数依赖的数量

c# - 延迟加载在 EntityFramework 6 中不起作用

c# - 绑定(bind)到字符串 ObservableCollection 的 DataGrid 不起作用

C# 和 Java 方法的区别

xml - 我需要以文本格式与不同的程序交换数据,你有什么建议?

oracle - 使用 expdp 和 impdp 迁移 Oracle 数据库

java - Oracle Java 存储过程

sql - 如何在Oracle SQL Developer工具中运行.sql文件来导入数据库?