c#实体框架EF 4.1在运行时更改架构和数据库名称

本文关键字:数据库 运行时 框架 实体 EF | 更新日期: 2023-09-27 18:29:48

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

我的应用程序是一个c#商业应用程序。我首先使用EF 4.1数据库。我从一个开发数据库连接中生成了模型,并创建了一个model.edmx文件和所有EF文件。

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

因此,myy的目标是在运行时更改连接字符串和模式参数,而不更改所有自动生成的edmx文件,也不更改VS生成的代码。

我环顾四周,发现:

对于EF早期版本:

在运行时更改架构名称-实体框架

http://efmodeladapter.codeplex.com

所有其他帖子都围绕着这一点展开。我甚至试图使用第一个邮政编码,但没有成功。

但我看到EF 4.1提供了更好的支持工具,但我找不到它的参考或示例。重要的是不要更改VS的自动生成代码。

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

我使用Oracle作为数据库服务器(由于Oracle将模式和用户混合在一起,所以情况更糟)。

c#实体框架EF 4.1在运行时更改架构和数据库名称

实际上,我也需要解决方案。我很快想出了解决方案,效果很好。我在互联网上找不到太多关于这方面的信息,所以我不确定"EF 4.1有更好的支持工具"。

具体的例子"在运行时更改模式名称-实体框架"对我来说并不完全有效,但经过一些小的修改,我使它发挥了作用。

这里有一个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/