c#实体框架EF 4.1在运行时更改模式和数据库名称 [英] c# Entity Framework EF 4.1 Change Schema and Database name at runtime

查看:137
本文介绍了c#实体框架EF 4.1在运行时更改模式和数据库名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I´ve searched for some topics, but did not find a concrete solution to my problem.

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

My app is a c# commercial app. I´m using EF 4.1 database first. I generate the model from a development database connection and that create a Model.edmx file and all EF stuff pretty fine.

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

My goal is to deliver an appplication to the customer and let him freely create the database and database user at his own. Do do it, at runtime I would get the username, password, database connection and schema name parameters to connect to customer database. In that way, to deploy the application all I need is to ask the customer to create a database and add the database parameters to the app config file.

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

So, myy goal is to change the connection string and schema parameter at runtime, without changing att all the auto generated edmx file, not touching the VS generated code.

我已经环顾四周:

对于EF早期版本:

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

http://efmodeladapter.codeplex.com

所有其他帖子都会在那边。我尝试使用第一个邮政编码没有成功。

All other posts are going around that. I tryed even to use the first post code with no success.

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

But I´ve seen that EF 4.1 comes with better support tools to do it, but I could not find references or examples to it. It´s important not to change the auto generated code from VS.

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

I´m pretty new to EF, so I would like to ask for help on accomplish the following tasks: a) Change connection string at runtime adding my username, password and database server/port parameters b) Change database schema

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

I´m using Oracle as a database server (that makes things worst as Oracle mixes schema and users together).

推荐答案

实际上,我需要解决方案太。我很快鞭打了解决方案,效果很好。我没有在互联网上找到很多关于这一点的信息,所以我不确定EF 4.1是否配备了更好的支持工具。

Actually, I needed solution for this too. I quickly whipped up solution, which works nicely. I didn't find much information about this in Internet, so I am not sure about the "EF 4.1 comes with better support tools to do it".

具体示例运行时更改模式名称 - 实体框架并不完全适用于我,但是通过一些细微的修改,我可以使用它。

The concrete example "Changing schema name on runtime - Entity framework" didn't entirely work for me, however with some minor modifications I got it working.

这是一个DatabaseUtils类,可以这样做:

Here is a DatabaseUtils class that can do it:

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 /

more info can be found here: http://bestplayah.com/entity-framework-dynamic-schema-changes-using-database-first-approach/

这篇关于c#实体框架EF 4.1在运行时更改模式和数据库名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆