1

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

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

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

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

我环顾四周,发现:

对于 EF 早期版本:

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

http://efmodeladapter.codeplex.com

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

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

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

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

4

1 回答 1

4

实际上,我也需要解决方案。我迅速提出了解决方案,效果很好。我在 Internet 上没有找到太多关于此的信息,因此我不确定“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/

于 2013-11-14T16:13:20.747 回答