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

查看:221
本文介绍了c#Entity Framework 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.

是在运行时更改连接字符串和模式参数,而不改变att所有自动生成的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:

在运行时更改模式名 - Entity Framework

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混合模式和用户在一起)。

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".

具体的例子

这里是一个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#Entity Framework EF 4.1在运行时更改模式和数据库名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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