如何在运行时创建XmlMappingSource?

时间:2009-02-25 10:38:27

标签: c# .net xml linq-to-sql

How to change LINQ O/R-M table name/source during runtime?的后续问题)

我需要在运行时更改LINQ 2 SQL O / R-Mapper表的表源。为此,我需要创建一个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);

我的问题:我找不到好的映射文档,因此提取必要的信息非常容易出错 - 也许有人可以指出我对映射的好文档,或者更好的是代码示例如何创建映射文件?

3 个答案:

答案 0 :(得分:1)

您是否考虑过使用LINQ to Entities,记录了LINQ to Entities的映射格式。

答案 1 :(得分:1)

使用Damien Guard的开源T4模板。他们可以做SQLMetal可以做的更多事情,而且你将拥有完整的T4引擎。

答案 2 :(得分: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;
    }`