2011-04-25 119 views
24

我想分享橫跨在Silverlight多個實體相同的數據庫信息..但我想連接字符串被命名爲XYZ,讓所有人訪問,從machine.config中的連接字符串...的實體框架連接字符串

實體的元數據部分將會有所不同,因爲我沒有將實體命名爲相同的名稱。

我可以在該元數據部分放置多個實體嗎?

下面是一個例子。我想使用此連接字符串,但請注意,我把多個實體的元數據部分..

基本上,我想利用這個連接字符串

<add name="XYZ" connectionString="metadata=res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SomeServer;Initial Catalog=SomeCatalog;Persist Security Info=True;User ID=Entity;Password=SomePassword;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" /> 

而且此連接字符串

<add name="XYZ" connectionString="metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SOMESERVER;Initial Catalog=SOMECATALOG;Persist Security Info=True;User ID=Entity;Password=Entity;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" /> 

爲了使這個連接字符串

<add name="XYZ" connectionString="metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl|res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SOMESERVER;Initial Catalog=SOMECATALOG;Persist Security Info=True;User ID=Entity;Password=SOMEPASSWORD;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" /> 

但它根本不起作用。這兩個項目都不能連接到它。

string encConnection = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString; 
Type contextType = typeof(test_Entities); 
object objContext = Activator.CreateInstance(contextType, encConnection); 
return objContext as test_Entities; 
+0

請提供代碼示例;你怎麼連接?它跨域嗎? – 2011-04-25 17:47:55

+0

相同的機器相同的域名..如果我有2個連接字符串分開它工作正常..但我會增加更多的項目和易於部署我希望他們都能夠從數據源相同的連接字符串對他們來說都是一樣的 – Rico 2011-04-25 18:18:12

回答

37

不幸的是,將多個實體上下文組合成單個命名連接是不可能的。如果要使用.config文件中的命名連接字符串來定義實體框架連接,則它們每個都必須具有不同的名稱。按照慣例,該名稱通常是上下文的名稱:

<add name="ModEntity" connectionString="metadata=res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SomeServer;Initial Catalog=SomeCatalog;Persist Security Info=True;User ID=Entity;Password=SomePassword;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" /> 
<add name="Entity" connectionString="metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SOMESERVER;Initial Catalog=SOMECATALOG;Persist Security Info=True;User ID=Entity;Password=Entity;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" /> 

但是,如果你最終命名空間衝突,你可以使用任何你想要的名稱,併產生時,它簡單地傳遞正確的名稱上下文:

var context = new Entity("EntityV2"); 

顯然,如果您使用的是一個工廠或依賴注入產生的背景這一戰略的效果最好。

另一種選擇是以編程方式生成每個上下文的整個連接字符串,然後將整個字符串傳遞給構造函數(而不僅僅是名稱)。

// Get "Data Source=SomeServer..." 
var innerConnectionString = GetInnerConnectionStringFromMachinConfig(); 
// Build the Entity Framework connection string. 
var connectionString = CreateEntityConnectionString("Entity", innerConnectionString); 
var context = new EntityContext(connectionString); 

怎麼是這樣的:

Type contextType = typeof(test_Entities); 
string innerConnectionString = ConfigurationManager.ConnectionStrings["Inner"].ConnectionString; 
string entConnection = 
    string.Format(
     "metadata=res://*/{0}.csdl|res://*/{0}.ssdl|res://*/{0}.msl;provider=System.Data.SqlClient;provider connection string=\"{1}\"", 
     contextType.Name, 
     innerConnectionString); 
object objContext = Activator.CreateInstance(contextType, entConnection); 
return objContext as test_Entities; 

...在你的machine.config如下:

<add name="Inner" connectionString="Data Source=SomeServer;Initial Catalog=SomeCatalog;Persist Security Info=True;User ID=Entity;Password=SomePassword;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" /> 

這樣,您就可以使用一個單一的連接字符串機器上每個項目的每個環境。

+0

那麼這裏的交易將有很多項目連接到這個數據庫,如果我更改數據庫,我不想改變20個連接字符串使其工作。所以目前我嵌入了像我正在修改我的問題 – Rico 2011-05-04 18:39:03

+0

@Rico:是的。因此,只需將連接字符串的「內部」部分放入Machine.Config中,然後根據該內部連接字符串生成每個Context的連接字符串。 – StriplingWarrior 2011-05-04 18:48:02

0

Silverlight應用程序不能直接訪問machine.config。

+0

網絡端做我的實體所在的地方...... – Rico 2011-04-25 17:57:48

2

首先嚐試瞭解實體框架連接字符串是如何工作的,然後您就會知道什麼是錯誤的。

  1. 你有兩個不同的模式,實體和ModEntity
  2. 這意味着你有兩個不同的上下文,每個上下文都有自己的存儲模型,兩者之間的概念模型和映射。
  3. 您只是簡單地組合了字符串,但實體的上下文將如何知道它必須拾取e​​ntity.csdl,並且ModEntity將取代modentity.csdl?那麼有人可以寫一些智能代碼,但我不認爲這是EF開發團隊的主要角色。
  4. 另外machine.config是個壞主意。
  5. 如果網絡應用程序被移動到不同的機器,或共享主機環境或出於維護目的,它可能會導致問題。
  6. 每個人都可以訪問它,你讓它變得不安全。如果任何人都可以在服務器上部署Web應用程序或任何.NET應用程序,則他們可以完全訪問包含敏感密碼信息的連接字符串。

另一種方法是,你可以創建自己的構造函數的情況下,並通過自己的連接字符串,你可以寫一些,如果條件等,從web.config中加載默認

更好的事情是做是,保持連接字符串不變,爲應用程序池提供一個身份,該身份將訪問數據庫服務器,並且不在連接字符串中包含用戶名和密碼。

1

我的理解是你想要與其中不同元數據相同的連接字符串。所以你可以使用下面給出的連接字符串並替換「」部分。我用相同的順序使用了給定的connectionString。

connectionString="<METADATA>provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SomeServer;Initial Catalog=SomeCatalog;Persist Security Info=True;User ID=Entity;Password=SomePassword;MultipleActiveResultSets=True&quot;" 

對於第一的connectionString與"metadata=res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;"

更換<METADATA>對於第二的connectionString與"metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl;"

更換<METADATA>第三的connectionString與"metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl|res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;"

快樂編碼代替<METADATA>

+0

嗯,這沒有工作 – Rico 2011-05-04 18:36:23

+0

它顯示一些錯誤? – Ravia 2011-05-06 06:13:08

5

不使用配置文件,您可以使用配置數據庫與範圍的systemConfig表並將所有設置添加到那裏。

CREATE TABLE [dbo].[SystemConfig] 
    ( 
     [Id] [int] IDENTITY(1, 1) 
       NOT NULL , 
     [AppName] [varchar](128) NULL , 
     [ScopeName] [varchar](128) NOT NULL , 
     [Key] [varchar](256) NOT NULL , 
     [Value] [varchar](MAX) NOT NULL , 
     CONSTRAINT [PK_SystemConfig_ID] PRIMARY KEY NONCLUSTERED ([Id] ASC) 
     WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
       IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
       ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
    ) 
ON [PRIMARY] 

GO 

SET ANSI_PADDING OFF 
GO 

ALTER TABLE [dbo].[SystemConfig] ADD CONSTRAINT [DF_SystemConfig_ScopeName] DEFAULT ('SystemConfig') FOR [ScopeName] 
GO 

利用這樣的配置表,你可以像這樣創建行:

從您的應用程序DAL(S)包裝EF,你可以很容易地檢索範圍的配置

然後。
如果您沒有使用dal(s)並直接與EF一起工作,則可以從SystemConfig表中創建實體,並根據您所在的應用程序使用該值。

+0

+1有趣的解決方案,我可能不得不嘗試一下。 – Maslow 2011-05-05 12:39:56

+0

這基本上是一個配置文件的替代品。唯一需要在配置中指定的是應用程序名稱和SystemConfigConnectionString ...其他所有內容都在數據庫中。很方便 :) – 2011-05-05 14:22:35

2

,能夠同樣EDMX訪問多個數據庫和數據庫提供商和反之亦然我使用以下技術:

1)定義的ConnectionManager:

2)修改創建的T4您ObjectContext的,這樣它會使用的ConnectionManager:

public partial class MyModelUnitOfWork : ObjectContext 
{ 
    public const string ContainerName = "MyModelUnitOfWork"; 
    public static readonly string ConnectionString 
     = ConnectionManager.GetConnectionString("MyModel"); 

3)添加以下行到App.Config中:

 
<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <connectionStrings> 
    <add name="MyModelUnitOfWork" connectionString=... /> 
    </connectionStrings> 
    <appSettings> 
    <add key="MyModelUnitOfWorkConnectionString" value="data source=MyPc\SqlExpress;initial catalog=MyDB;integrated security=True;multipleactiveresultsets=True" /> 
    <add key="MyModelUnitOfWorkProvider" value="System.Data.SqlClient" /> 
    </appSettings> 
</configuration> 

ConnectionManager會將ConnectionString和Provider替換爲App.Config中的任何內容。

您可以對所有ObjectContexts使用相同的ConnectionManager(因此它們都從App.Config讀取相同的設置),或者編輯T4,以便爲每個(在其自己的命名空間中)創建一個ConnectionManager,以便每個讀取都是分開的設置。