2009-02-25 63 views
1

(對How to change LINQ O/R-M table name/source during runtime?的後續問題)如何在運行時創建XmlMappingSource?

我需要在運行時更改LINQ 2 SQL O/R映射表的表來源。要實現這一點,我需要創建一個XmlMappingSource。在命令行上,我可以使用SqlMetal來創建這個映射文件,但是我想在運行時在內存中創建映射文件。 的XmlMappingSource是一個簡單的XML文件,看起來像這樣:

<?xml version="1.0" encoding="utf-8"?> 
<Database Name="MyDatabase" xmlns="http://schemas.microsoft.com/linqtosql/mapping/2007"> 
    <Table Name="dbo.MyFirstTable" Member="MyFirstTable"> 
    <Type Name="MyFirstTable"> 
     <Column Name="ID" Member="ID" Storage="_ID" DbType="UniqueIdentifier NOT NULL" IsPrimaryKey="true" IsDbGenerated="true" AutoSync="OnInsert" /> 
     <Association Name="WaStaArtArtikel_WaVerPreisanfragen" Member="WaStaArtArtikel" Storage="_WaStaArtArtikel" ThisKey="ArtikelID" OtherKey="ID" IsForeignKey="true" /> 
    </Type> 
    </Table> 
    <Table Name="dbo.MySecondTable" Member="MySecondTable"> 
    <Type Name="MySecondTable"> 
     <Column Name="ID" Member="ID" Storage="_ID" DbType="UniqueIdentifier NOT NULL" IsPrimaryKey="true" IsDbGenerated="true" AutoSync="OnInsert" /> 
     <Column Name="FirstTableID" Member="FirstTableID" Storage="_FirstTableID" DbType="UniqueIdentifier NOT NULL" /> 
     <Association Name="MySecondTable_MyFirstTable" Member="MyFirstTable" Storage="_MyFirstTable" ThisKey="FirstTableID" OtherKey="ID" IsForeignKey="true" /> 
    </Type> 
    </Table> 
</Database> 

這應該是可以使用反射來創建,例如,我可以從數據方面得到數據庫名是這樣的:

using System.Data.Linq.Mapping; 
using System.Xml.Linq; 

XDocument mapWriter = new XDocument(); 
DatabaseAttribute[] catx = (DatabaseAttribute[])typeof(WcfInterface.WaDataClassesDataContext).GetCustomAttributes(typeof(DatabaseAttribute), false); 
XElement xDatabase = new XElement("Database"); 
xDatabase.Add(new XAttribute("Name", catx[0].Name)); 
mapWriter.Add(xDatabase); 

我的問題:我無法找到良好的映射文檔,因此提取必要的信息非常容易出錯 - 也許有人可以將我指向映射的良好文檔,或者甚至更好地指向代碼示例如何創建映射文件?

+0

建議你說的LINQ到在此開始明確SQL來避免與LINQ混亂實體(這是更爲的比LINQ to SQL更爲豐富的映射功能)。 – Richard 2009-02-25 11:36:41

+0

是的,對,完成 - 謝謝! – Sam 2009-02-25 13:29:49

回答

1

您是否考慮過使用LINQ to Entities,將LINQ to Entities的映射格式記錄在案。

+0

其實,我並沒有真正意識到L2E是取代L2S的。 那麼,在L2E中,可以在運行時更改映射嗎? – Sam 2009-02-25 13:28:52

1

使用Damien Guard的開源T4模板。他們完成SQLMetal可以完成的所有工作以及更多功能,並且您將擁有完整的T4引擎。

0

我剛剛有同樣的問題,我也沒有選擇改變項目,因爲它爲時已晚。

我需要更新我的解決方案中的映射文件中的數據庫名稱。 該解決方案有效。

我的數據庫映射

<?xml version="1.0" encoding="utf-8"?> 
<Database Name="DatabaseName" xmlns="http://schemas.microsoft.com/linqtosql/mapping/2007"> 
    <Table Name="dbo.tblDictionary" Member="TblDictionary"> 
    <Type Name="TblDictionary"> 
     <Column Name="lngRecordID" Member="LngRecordID" Storage="_LngRecordID" DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" IsDbGenerated="true" AutoSync="OnInsert" /> 
     <Column Name="txtWord" Member="TxtWord" Storage="_TxtWord" DbType="VarChar(50) NOT NULL" CanBeNull="false" /> 
    </Type> 
    </Table> 
</Database> 

終於代碼:

class Program 
    { 
     static void Main(string[] args) 
     { 

     // to get embeded file name you have to add namespace of the application 
     const string embeddedFilename = "ConsoleApplication3.FrostOrangeMappings.xml"; 
     // load file into stream 
     var embeddedStream = GetEmbeddedFile(embeddedFilename); 
     // process stream 
     ProcessStreamToXmlMappingSource(embeddedStream); 
     Console.ReadKey(); 


    } 

    private static void ProcessStreamToXmlMappingSource(Stream stream) 
    { 

     const string newDatabaseName = "pavsDatabaseName";  

     var mappingFile = new XmlDocument(); 
     mappingFile.Load(stream); 
     stream.Close(); 


     // populate collection of attribues 
     XmlAttributeCollection collection = mappingFile.DocumentElement.Attributes; 

     var attribute = collection["Name"]; 
     if(attribute==null) 
     { 
      throw new Exception("Failed to find Name attribute in xml definition"); 
     } 

     // set new database name definition 
     collection["Name"].Value = newDatabaseName; 

     //display xml to user 
     var stringWriter = new StringWriter(); 
      using (var xmlTextWriter = XmlWriter.Create(stringWriter)) 
      { 
       mappingFile.WriteTo(xmlTextWriter); 
       xmlTextWriter.Flush(); 
       stringWriter.GetStringBuilder(); 
      } 
     Console.WriteLine(stringWriter.ToString()); 

    } 
    /// <summary> 
    /// Loads file into stream 
    /// </summary> 
    /// <param name="fileName"></param> 
    /// <returns></returns> 
    private static Stream GetEmbeddedFile(string fileName) 
    { 
     var assembly = Assembly.GetExecutingAssembly(); 
     var stream = assembly.GetManifestResourceStream(fileName); 

     if (stream == null) 
      throw new Exception("Could not locate embedded resource '" + fileName + "' in assembly"); 

     return stream; 
    }`