【问题标题】:Reference between EF Designer view and custom T4 templateEF 设计器视图和自定义 T4 模板之间的引用
【发布时间】:2011-12-14 05:44:12
【问题描述】:

我按照these steps 自定义了EF T4 代码生成。一切都很好,但似乎是 EF 设计器视图,您可以在其中将表视为“实体”以及属性与表中的列之间的映射。我的代码显示了我在 T4 模板中所做的更改,但设计器没有。此外,如果我向设计器添加新表,它不会更新代码。我有什么遗漏吗?

编辑: 到目前为止,我所做的自定义是为每个生成的实体添加一个自定义属性。下面是 T4 代码:

region.Begin(GetResourceString("Template_RegionPrimitiveProperties"));

    WriteLine("");
    Write("\t");
    WriteLine("[EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]");
    Write("\t");
    WriteLine("[DataMemberAttribute()]");
    Write("\t");
    WriteLine("public Guid OriginalId { get; set; }");

    foreach (EdmProperty property in entity.Properties.Where(p => p.DeclaringType == entity && p.TypeUsage.EdmType is PrimitiveType))

所有“Write”和“WriteLine”调用都是我自己的。我知道这不是最好的方法,但我仍然掌握了 T4 的窍门。如果我写这篇文章的方式有问题,请指出我应该如何添加这个自定义属性的正确方向。

【问题讨论】:

  • 你是如何定制它的?保存 .edmx 文件后也不更新?
  • 我用到目前为止添加的“代码”编辑了问题。
  • @JeffN825 说对了。您应该手动添加 id 属性的表中的 id 列有什么问题?
  • 如果您的属性不在数据库中,则它不能在设计器中,否则您的代码将无法正常工作。
  • 自我跟踪实体对于 N-Tier 来说不是很好......因为它们高度特定于实体框架。实体框架充其量只是一个不确定的解决方案,您可能希望在未来转向一个经过深思熟虑的 ORM ......所以恕我直言,POCO 确实是要走的路。

标签: .net entity-framework t4


【解决方案1】:

设计器显示 edmx XML,而不是它生成的 C# 代码。因此,您可能正在修改生成的代码……但这不会影响设计器显示的内容。

进一步...如果您尝试使用您的自定义重写 edmx XML 本身,以便它在设计器中显示,您必须确保在 csdl、msl 和 ssdl 中正确映射新属性,否则 edmx 将无法验证。

顺便说一句,使用 T4 模板修改 edmx xml 也没那么糟糕。这是我编写的一个示例,用于在保存 edmx 时(使用 Database Generation Power Pack 中的一些模板)使用 TPH(每个层次结构的表)SSDL 和 MSL 自动生成和更新 edmx。这存在于我的实体生成 T4 模板中,每当保存 edmx 时都会调用该模板。

<#@ assembly name="System.Core" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="System.Xml.Linq" #>
<#@ assembly name="System.Data" #>
<#@ assembly name="System.Data.Entity" #>
<#@ assembly name="System.Data.Entity.Design" #>
<#@ assembly name="$(DevEnvDir)Microsoft.Data.Entity.Design.DatabaseGeneration.dll"#>
<#@ assembly name="$(ProjectDir)..\..\Dependencies\Microsoft.Data.Entity.Design.DatabaseGenerationToolkit.dll"#>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Data" #>
<#@ import namespace="System.Data.Common" #>
<#@ import namespace="System.Data.Entity.Design" #>
<#@ import namespace="System.Data.Metadata.Edm" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Globalization" #>
<#@ import namespace="Microsoft.Data.Entity.Design.DatabaseGeneration" #>
<#@ import namespace="Microsoft.Data.Entity.Design.DatabaseGenerationToolkit" #>
<#@ import namespace="System.Runtime.Remoting.Messaging" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#@ import namespace="System.IO" #>
<#@ template language="C#" debug="true" hostspecific="true" #>
<#@ include file="GenerateTSQL.Utility.ttinclude"#>
<#@ include file="GenerateEDM.Utility.ttinclude"#>
<#@ output extension = ".xml" #>
<#
string inputFile = @"Model.edmx";

inputFile = Host.ResolvePath(inputFile);

var ssdlTransformPath = Host.ResolvePath(@"GenerateSSDL_TPH.tt");
var mslTransformPath = Host.ResolvePath(@"GenerateMSL_TPH.tt");

var document = new XmlDocument();
document.PreserveWhitespace = true;

document.Load(inputFile);
var namespaceManager = new XmlNamespaceManager(document.NameTable);
namespaceManager.AddNamespace("edmx", "http://schemas.microsoft.com/ado/2008/10/edmx");
namespaceManager.AddNamespace("ssdl", "http://schemas.microsoft.com/ado/2009/02/edm/ssdl");

var schema = "model";
var schemaNode = document.SelectSingleNode("//edmx:DesignerProperty[@Name='DefaultDatabaseSchema']", namespaceManager);
if (schemaNode != null) schema = schemaNode.Attributes["Value"].Value;

var csdl = document.SelectSingleNode("//edmx:ConceptualModels", namespaceManager).InnerXml;

CallContext.SetData(EdmConstants.csdlInputName, csdl);
CallContext.SetData(EdmParameterBag.ParameterName.TargetVersion.ToString(), new Version("2.0.0.0"));
CallContext.SetData(EdmParameterBag.ParameterName.ProviderInvariantName.ToString(), "System.Data.SqlClient");
CallContext.SetData(EdmParameterBag.ParameterName.ProviderManifestToken.ToString(), "2005");
CallContext.SetData(EdmParameterBag.ParameterName.DatabaseSchemaName.ToString(), schema);
CallContext.SetData(EdmParameterBag.ParameterName.DatabaseName.ToString(), document.SelectSingleNode("//ssdl:EntityContainer", namespaceManager).Attributes["Name"].Value);
CallContext.SetData(EdmParameterBag.ParameterName.EdmxPath.ToString(), inputFile);

string ssdl = new Engine().ProcessTemplate(File.ReadAllText(ssdlTransformPath), Host);
var ssdlNode = document.SelectSingleNode("//edmx:StorageModels", namespaceManager);
ssdlNode.InnerXml = ssdl;

CallContext.SetData(EdmConstants.existingSsdlInputName, ssdl);
CallContext.SetData(EdmConstants.ssdlOutputName, ssdl);

string msl = new Engine().ProcessTemplate(File.ReadAllText(mslTransformPath), Host);
var mslNode = document.SelectSingleNode("//edmx:Mappings", namespaceManager);
mslNode.InnerXml = msl;

var isChanged = document.OuterXml != File.ReadAllText(inputFile);

if (isChanged) 
{
    document.Save(inputFile);
}
#>

【讨论】:

  • @Jeff 这怎么会出现在您的 EF T4 模板中? EF T4 模板的输出扩展名为 .cs。
猜你喜欢
  • 2010-11-03
  • 1970-01-01
  • 2021-05-24
  • 1970-01-01
  • 2015-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-26
相关资源
最近更新 更多