2011-12-01 127 views
4

數據庫中的屬性全部爲小寫,並且使用下劃線進行單詞分隔。例如: -實體框架POCO實體模板:格式屬性名稱

customer_order_id 

我想要的屬性名符合我的PropertyNameCodingConvention,即:customer_order_id -> CustomerOrderId

我已經改變了T4模板來完成這一點,但我很好奇,如果有已經上市的解決方案。

+0

只是好奇你有沒有看過自定義約定來完成這個? http://blogs.msdn.com/b/adonet/archive/2011/01/10/ef-feature-ctp5-pluggable-conventions.aspx –

+0

是的,我的理解是適用於CodeFirst方法的,這與Code我正在做,即我有數據庫,並需要生成C#代碼(所以這是'代碼最後'的方法)。 –

回答

0

這需要改變的模板,但這裏是我是如何做的:

  1. 添加到EntityPoco.tt(最後收盤前右「#>」標記)的結尾:

    private string N(string input) { 
        return System.Text.RegularExpressions.Regex.Replace(input, 
         "(?:_|^)([a-z])", 
         match => match.Groups[1].Value.ToUpper()).Replace("_", ""); 
    } 
    
  2. 將所有輸出屬性名稱的地方(總共6個,請參閱下面的代碼)包裝在一起。

這是一個完整的文本:

<# 
//********************************************************* 
// 
// Copyright (c) Microsoft. All rights reserved. 
// This code is licensed under the Microsoft Public License. 
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 
// 
//********************************************************* 
#> 
<#@ template language="C#" debug="false" hostspecific="true"#> 
<#@ include file="EF.Utility.CS.ttinclude"#><#@ 
output extension=".cs"#><# 

CodeGenerationTools code = new CodeGenerationTools(this); 
MetadataLoader loader = new MetadataLoader(this); 
CodeRegion region = new CodeRegion(this, 1); 
MetadataTools ef = new MetadataTools(this); 

string inputFile = @"PSI.Entities.edmx"; 
EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile); 
string namespaceName = code.VsNamespaceSuggestion(); 

EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this); 
WriteHeader(fileManager); 

foreach (var entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name)) 
{ 
    fileManager.StartNewFile(entity.Name + ".cs"); 
    BeginNamespace(namespaceName, code); 
#> 
<#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#>partial class <#=code.Escape(entity)#><#=code.StringBefore(" : ", code.Escape(entity.BaseType))#> 
{ 
<# 
    var propertiesWithDefaultValues = entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity && p.DefaultValue != null); 
    var collectionNavigationProperties = entity.NavigationProperties.Where(np => np.DeclaringType == entity && np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many); 
    var complexProperties = entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity); 

    if (propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() || complexProperties.Any()) 
    { 
#> 
    public <#=code.Escape(entity)#>() 
    { 
<# 
     foreach (var edmProperty in propertiesWithDefaultValues) 
     { 
#> 
     this.<#=N(code.Escape(edmProperty))#> = <#=code.CreateLiteral(edmProperty.DefaultValue)#>; 
<# 
     } 

     foreach (var navigationProperty in collectionNavigationProperties) 
     { 
#> 
     this.<#=N(code.Escape(navigationProperty))#> = new HashSet<<#=code.Escape(navigationProperty.ToEndMember.GetEntityType())#>>(); 
<# 
     } 

     foreach (var complexProperty in complexProperties) 
     { 
#> 
     this.<#=N(code.Escape(complexProperty))#> = new <#=code.Escape(complexProperty.TypeUsage)#>(); 
<# 
     } 
#> 
    } 

<# 
    } 

    var primitiveProperties = entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity); 
    if (primitiveProperties.Any()) 
    { 
     foreach (var edmProperty in primitiveProperties) 
     { 
      WriteProperty(code, edmProperty); 
     } 
    } 

    if (complexProperties.Any()) 
    { 
#> 

<# 
     foreach(var complexProperty in complexProperties) 
     { 
      WriteProperty(code, complexProperty); 
     } 
    } 

    var navigationProperties = entity.NavigationProperties.Where(np => np.DeclaringType == entity); 
    if (navigationProperties.Any()) 
    { 
#> 

<# 
     foreach (var navigationProperty in navigationProperties) 
     { 
      WriteNavigationProperty(code, navigationProperty); 
     } 
    } 
#> 
} 

<# 
    EndNamespace(namespaceName); 
} 

foreach (var complex in ItemCollection.GetItems<ComplexType>().OrderBy(e => e.Name)) 
{ 
    fileManager.StartNewFile(complex.Name + ".cs"); 
    BeginNamespace(namespaceName, code); 
#> 
<#=Accessibility.ForType(complex)#> partial class <#=code.Escape(complex)#> 
{ 
<# 
    var complexProperties = complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex); 
    var propertiesWithDefaultValues = complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex && p.DefaultValue != null); 

    if (propertiesWithDefaultValues.Any() || complexProperties.Any()) 
    { 
#> 
    public <#=code.Escape(complex)#>() 
    { 
<# 
     foreach (var edmProperty in propertiesWithDefaultValues) 
     { 
#> 
     this.<#=N(code.Escape(edmProperty))#> = <#=code.CreateLiteral(edmProperty.DefaultValue)#>; 
<# 
     } 

     foreach (var complexProperty in complexProperties) 
     { 
#> 
     this.<#=N(code.Escape(complexProperty))#> = new <#=code.Escape(complexProperty.TypeUsage)#>(); 
<# 
     } 
#> 
    } 

<# 
    } 

    var primitiveProperties = complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex); 
    if (primitiveProperties.Any()) 
    { 
     foreach(var edmProperty in primitiveProperties) 
     { 
      WriteProperty(code, edmProperty); 
     } 
    } 

    if (complexProperties.Any()) 
    { 
#> 

<# 
     foreach(var edmProperty in complexProperties) 
     { 
      WriteProperty(code, edmProperty); 
     } 
    } 
#> 
} 

<# 
    EndNamespace(namespaceName); 
} 

if (!VerifyTypesAreCaseInsensitiveUnique(ItemCollection)) 
{ 
    return ""; 
} 

fileManager.Process(); 

#> 
<#+ 
void WriteHeader(EntityFrameworkTemplateFileManager fileManager) 
{ 
    fileManager.StartHeader(); 
#> 
//------------------------------------------------------------------------------ 
// <auto-generated> 
// This code was generated from a template. 
// 
// Manual changes to this file may cause unexpected behavior in your application. 
// Manual changes to this file will be overwritten if the code is regenerated. 
// </auto-generated> 
//------------------------------------------------------------------------------ 

using System; 
using System.Collections.Generic; 

<#+ 
    fileManager.EndBlock(); 
} 

void BeginNamespace(string namespaceName, CodeGenerationTools code) 
{ 
    CodeRegion region = new CodeRegion(this); 
    if (!String.IsNullOrEmpty(namespaceName)) 
    { 
#> 
namespace <#=code.EscapeNamespace(namespaceName)#> 
{ 
<#+ 
     PushIndent(CodeRegion.GetIndent(1)); 
    } 
} 


void EndNamespace(string namespaceName) 
{ 
    if (!String.IsNullOrEmpty(namespaceName)) 
    { 
     PopIndent(); 
#> 
} 
<#+ 
    } 
} 

void WriteProperty(CodeGenerationTools code, EdmProperty edmProperty) 
{ 
    WriteProperty(Accessibility.ForProperty(edmProperty), 
        code.Escape(edmProperty.TypeUsage), 
        code.Escape(edmProperty), 
        code.SpaceAfter(Accessibility.ForGetter(edmProperty)), 
        code.SpaceAfter(Accessibility.ForSetter(edmProperty))); 
} 

void WriteNavigationProperty(CodeGenerationTools code, NavigationProperty navigationProperty) 
{ 
    var endType = code.Escape(navigationProperty.ToEndMember.GetEntityType()); 
    WriteProperty(PropertyVirtualModifier(Accessibility.ForProperty(navigationProperty)), 
        navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType, 
        code.Escape(navigationProperty), 
        code.SpaceAfter(Accessibility.ForGetter(navigationProperty)), 
        code.SpaceAfter(Accessibility.ForSetter(navigationProperty))); 
} 

void WriteProperty(string accessibility, string type, string name, string getterAccessibility, string setterAccessibility) 
{ 
#> 
    <#=accessibility#> <#=type#> <#=N(name)#> { <#=getterAccessibility#>get; <#=setterAccessibility#>set; } 
<#+ 
} 

string PropertyVirtualModifier(string accessibility) 
{ 
    return accessibility + (accessibility != "private" ? " virtual" : ""); 
} 

bool VerifyTypesAreCaseInsensitiveUnique(EdmItemCollection itemCollection) 
{ 
    var alreadySeen = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase); 
    foreach(var type in itemCollection.GetItems<StructuralType>()) 
    { 
     if (!(type is EntityType || type is ComplexType)) 
     { 
      continue; 
     } 

     if (alreadySeen.ContainsKey(type.FullName)) 
     { 
      Error(String.Format(CultureInfo.CurrentCulture, "This template does not support types that differ only by case, the types {0} are not supported", type.FullName)); 
      return false; 
     } 
     else 
     { 
      alreadySeen.Add(type.FullName, true); 
     } 
    } 

    return true; 
} 

private string N(string input) { 
    return System.Text.RegularExpressions.Regex.Replace(input, "(?:_|^)([a-z])", match => match.Groups[1].Value.ToUpper()).Replace("_", ""); 
} 
#> 
+0

需要注意的是,如果使用POCO對象將屬性映射到實體(在概念模型中),則根據屬性名稱進行映射,因此_just_更改屬性名稱將不起作用。您還需要更改概念模型實體屬性名稱或使用屬性指定映射(POCO->實體)或更改概念模型(CSL)中的屬性名稱 –

1

在EDMX文件,你有兩個不同的模式,和一個映射架構。你可以做的是,你可以修改概念模式並更改屬性名稱,但是刷新EDMX可能會擦除這些信息。但通過這樣做,您根本不必更改模板。

+0

您是對的,這是一個選項,但它有幾個明顯的缺點:1.您對於清爽的EDM是正確的。 2.手動更改名稱並不好玩。 3.我不能使用正則表達式(不在VS中)更改名稱。 –