(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);
我的问题:我找不到好的映射文档,因此提取必要的信息非常容易出错 - 也许有人可以指出我对映射的好文档,或者更好的是代码示例如何创建映射文件?
答案 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;
}`