MVC 4 EntityConnection动态架构

时间:2015-02-13 17:00:56

标签: c# sql-server asp.net-mvc entity-framework

是否可以在运行时将数据库模式映射到构建动态EntityConnection?

我的下面有一个函数连接到我们的内部数据库,以返回必要的凭据:

public string GetEntityConnection(int? portalId)
{
    const string providerName = "System.Data.SqlClient";

    var entityBuilder = new EntityConnectionStringBuilder();

    var portalConnections = _portalAdminEntities.Portal_connections.SingleOrDefault(m => m.Portal_ID == portalId);

    if (portalConnections != null)
    {
        var sqlBuilder = new SqlConnectionStringBuilder
        {
            DataSource = portalConnections.PortalServer,
            InitialCatalog = portalConnections.PortalDatabase,
            UserID = portalConnections.PortalUsername,
            Password = portalConnections.PortalPassword,
            PersistSecurityInfo = true
        };

        var providerString = sqlBuilder.ToString();

        entityBuilder = new EntityConnectionStringBuilder
        {
            Provider = providerName,
            ProviderConnectionString = providerString,
            Metadata = @"res://*/Models.PortalAdmin.csdl|res://*/Models.PortalAdmin.ssdl|res://*/Models.PortalAdmin.msl"
        };
    }

    return entityBuilder.ToString();
}

然后我调用这样的函数将数据上传到我们的远程服务器:

using (var portalAdminEntities = new PortalAdminEntities(new EntityConnection(_df.GetEntityConnection(model.portalId))))
{
    portalAdminEntities.InsertPageDetails(model.pageId, portalId, model.title, model.content);
}

尽管已成功连接到我们的远程服务器,但由于远程服务器上的数据库架构不同,无法找到实际的存储过程。

我认为该问题与Models.PortalAdmin.msl有关,因为此文件是由Visual Studio 2010在创建实体框架以连接到我们的内部数据库时生成的,因此存储了架构。在这种情况下,我们的内部架构为dbo,而在外部我们使用somethingelse(由我们的外部托管服务提供商控制)。

在连接执行远程任务时,是否可以绕过msl文件或模式定义?

2 个答案:

答案 0 :(得分:0)

我认为你不想绕过msl或任何生成的文件。您可以手动删除dbo。来自msl,ssdl和csdl,如果你想要或通过Ef模型属性,这意味着db将在任何环境中工作。

答案 1 :(得分:0)

进一步调查发现,Visual Studio 2010生成的csdl,msdl和ssdl文件需要在运行时导入并进行操作>我在下面的更新解决方案允许使用除dbo之外的模式在运行时创建动态实体连接:

public EntityConnection GetEntityConnection(int? portalId, string modelName)
{
    var serverName = "";
    var databaseName = "";
    var username = "";
    var password = "";

    var portalConnections = _portalAdminEntities.Portal_connections.SingleOrDefault(m => m.Portal_ID == portalId);

    if (portalConnections != null)
    {
        serverName = portalConnections.PortalServer;
        databaseName = portalConnections.PortalDatabase;
        username = portalConnections.PortalUsername;
        password = portalConnections.PortalPassword;
    }

    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(databaseName);
        }
    }

    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);

    const string providerName = "System.Data.SqlClient";

    var sqlBuilder = new SqlConnectionStringBuilder
    {
        DataSource = serverName,
        InitialCatalog = databaseName,
        UserID = username,
        Password = password,
        PersistSecurityInfo = true
    };

    var providerString = sqlBuilder.ToString();

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

    var connection = DbProviderFactories.GetFactory(entityBuilder.Provider).CreateConnection();

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

        return null;
    }

    connection.ConnectionString = entityBuilder.ProviderConnectionString;

    return new EntityConnection(workspace, connection);
}

using (var portalAdminEntities = new PortalAdminEntities(_df.GetEntityConnection(model.Portal_ID, Models.PortalAdmin")))
{
    portalAdminEntities.InsertPageDetails(model.pageId, portalId, model.title, model.content);
}

我希望这对其他人有用: - )