2010-11-19 48 views
2

我試圖讓表名自動重命名以去掉EF4中的前導前綴。我知道它可以在GUI中完成,但是,我的公司在Visio中創建了數據庫模式,並使用它在SQL中創建數據庫創建腳本。我們經常這樣做,有時會有很多表格,所以使用GUI並不是一個理想的解決方案。導入時的EF4 Strip表前綴

是否需要修改.edmx文件上的屬性以從數據庫表中剝離已定義的前綴,以便實體類是我們期望的方式?

回答

7

我們想出的最簡單的解決方案是創建一個新的控制檯應用程序,它執行重命名edmx文件中所有內容的低級別工作;可以通過'arguments'= $(ItemPath),'initial directory'= $(ItemDir),'提示參數'= true'和'使用輸出窗口'將應用程序添加到Visual Studio的工具菜單(添加外部工具) = true,然後可以選擇EDMX文件執行。在我們的例子中,我們需要去除下劃線,並將名稱轉換爲駱駝大小寫(將下劃線解釋爲字詞分隔符),併除去前綴。

我會忽略代碼的其餘部分(如Transform.Standard方法,錯誤處理和附加參數的剝離),因爲它寫得太糟糕了,因此在重構時太晚了:P;但很容易解釋第一個字符串之後的其餘參數,從名稱等等剝離 - 這個主要代碼只是關於EDMX文件所需的修改。如果你使用VS作爲外部工具,你可以在'arguments'中的$(ItemPath)之後指定其餘的字符串。

請注意,這並未廣泛測試,並且其他EDMX文件中可能還有其他信息,但我沒有注意到(但我懷疑它)。另外,我從網上的其他地方獲得了部分代碼,但沒有記下確切的地方,所以很抱歉!信用應該是相應的。此外,當然,這將是作爲一個擴展的VS2010好多了,但是我根本沒有足夠的時間來做到這一點 - 如果你的某個地方鏈接它,我就會改用;)

if (_args.Count < 1) return; 

string file = _args.First(); 
if (!File.Exists(file)) 
{ 
    wait("Could not find specified file."); 
    return; 
} 
if (Path.GetExtension(file) != ".edmx") 
{ 
    wait("This works only on EDMX files."); 
    return; 
} 

//processing: 

Console.WriteLine("Creating backup: " + Path.ChangeExtension(file, ".bak")); 
File.Copy(file, Path.ChangeExtension(file, ".bak"), true); 

Console.WriteLine("Reading target document..."); 

XDocument xdoc = XDocument.Load(file); 

const string CSDLNamespace = "http://schemas.microsoft.com/ado/2008/09/edm"; 
const string MSLNamespace = "http://schemas.microsoft.com/ado/2008/09/mapping/cs"; 
const string DiagramNamespace = "http://schemas.microsoft.com/ado/2008/10/edmx"; 

XElement csdl = xdoc.Descendants(XName.Get("Schema", CSDLNamespace)).First(); 
XElement msl = xdoc.Descendants(XName.Get("Mapping", MSLNamespace)).First(); 
XElement designerDiagram = xdoc.Descendants(XName.Get("Diagram", DiagramNamespace)).First(); 

//modifications for renaming everything, not just table names: 

string[] CSDLpaths = new string[] 
{ 
    "EntityContainer/EntitySet.Name", 
    "EntityContainer/EntitySet.EntityType", 
    "EntityContainer/AssociationSet/End.EntitySet", 
    "EntityType.Name", 
    "EntityType/Key/PropertyRef/Name", 
    "EntityType/Property.Name", 
    "EntityType/NavigationProperty.Name", 
    "Association/End.Type", 
    "Association//PropertyRef.Name", 

}; 

#region CSDL2 

Console.WriteLine("Modifying CSDL..."); 
Console.WriteLine(" - modifying entity sets..."); 

foreach (var entitySet in csdl.Element(XName.Get("EntityContainer", CSDLNamespace)).Elements(XName.Get("EntitySet", CSDLNamespace))) 
{ 
    entitySet.Attribute("Name").Value = Transform.Standard(entitySet.Attribute("Name").Value); 
    entitySet.Attribute("EntityType").Value = Transform.Standard(entitySet.Attribute("EntityType").Value); 
} 

Console.WriteLine(" - modifying association sets..."); 
foreach (var associationSet in csdl.Element(XName.Get("EntityContainer", CSDLNamespace)).Elements(XName.Get("AssociationSet", CSDLNamespace))) 
{ 
    foreach (var end in associationSet.Elements(XName.Get("End", CSDLNamespace))) 
    { 
     end.Attribute("EntitySet").Value = Transform.Standard(end.Attribute("EntitySet").Value); 
    } 
} 

Console.WriteLine(" - modifying entity types..."); 
foreach (var entityType in csdl.Elements(XName.Get("EntityType", CSDLNamespace))) 
{ 
    entityType.Attribute("Name").Value = Transform.Standard(entityType.Attribute("Name").Value); 

    foreach (var key in entityType.Elements(XName.Get("Key", CSDLNamespace))) 
    { 
     foreach (var propertyRef in key.Elements(XName.Get("PropertyRef", CSDLNamespace))) 
     { 
      propertyRef.Attribute("Name").Value = Transform.Standard(propertyRef.Attribute("Name").Value); 
     } 
    } 

    foreach (var property in entityType.Elements(XName.Get("Property", CSDLNamespace))) 
    { 
     property.Attribute("Name").Value = Transform.Standard(property.Attribute("Name").Value); 
    } 

    foreach (var navigationProperty in entityType.Elements(XName.Get("NavigationProperty", CSDLNamespace))) 
    { 
     navigationProperty.Attribute("Name").Value = Transform.Standard(navigationProperty.Attribute("Name").Value); 
    } 

} 

Console.WriteLine(" - modifying associations..."); 
foreach (var association in csdl.Elements(XName.Get("Association", CSDLNamespace))) 
{ 
    foreach (var end in association.Elements(XName.Get("End", CSDLNamespace))) 
    { 
     end.Attribute("Type").Value = Transform.Standard(end.Attribute("Type").Value); 
    } 
    foreach (var propref in association.Descendants(XName.Get("PropertyRef", CSDLNamespace))) 
    { 
     //propertyrefs are contained in constraints 
     propref.Attribute("Name").Value = Transform.Standard(propref.Attribute("Name").Value); 
    } 
} 

#endregion 

#region MSL2 

Console.WriteLine("Modifying MSL..."); 
Console.WriteLine(" - modifying entity set mappings..."); 

foreach (var entitySetMapping in msl.Element(XName.Get("EntityContainerMapping", MSLNamespace)).Elements(XName.Get("EntitySetMapping", MSLNamespace))) 
{ 
    entitySetMapping.Attribute("Name").Value = Transform.Standard(entitySetMapping.Attribute("Name").Value); 

    foreach (var entityTypeMapping in entitySetMapping.Elements(XName.Get("EntityTypeMapping", MSLNamespace))) 
    { 
     entityTypeMapping.Attribute("TypeName").Value = Transform.Standard(entityTypeMapping.Attribute("TypeName").Value); 
     foreach 
     (var scalarProperty in 
     (entityTypeMapping.Element(XName.Get("MappingFragment", MSLNamespace))).Elements(XName.Get("ScalarProperty", MSLNamespace)) 
     ) 
     { 
      scalarProperty.Attribute("Name").Value = Transform.Standard(scalarProperty.Attribute("Name").Value); 
     } 
    } 
} 

Console.WriteLine(" - modifying association set mappings..."); 

foreach (var associationSetMapping in msl.Element(XName.Get("EntityContainerMapping", MSLNamespace)).Elements(XName.Get("AssociationSetMapping", MSLNamespace))) 
{ 
    foreach (var endProperty in associationSetMapping.Elements(XName.Get("EndProperty", MSLNamespace))) 
    { 
     foreach (var scalarProperty in endProperty.Elements(XName.Get("ScalarProperty", MSLNamespace))) 
     { 
      scalarProperty.Attribute("Name").Value = Transform.Standard(scalarProperty.Attribute("Name").Value); 
     } 
    } 
} 
#endregion 


#region Designer 

Console.WriteLine("Modifying designer content..."); 
foreach (var item in designerDiagram.Elements(XName.Get("EntityTypeShape", DiagramNamespace))) 
{ 
    item.Attribute("EntityType").Value = Transform.Standard(item.Attribute("EntityType").Value); 
} 

#endregion 

Console.WriteLine("Writing result..."); 

using (XmlTextWriter writer = new XmlTextWriter(args[0], Encoding.Default)) 
{ 
    writer.Formatting = Formatting.Indented; 
    xdoc.WriteTo(writer); 
} 

編輯:添加上面代碼使用的Transform類。此外,請注意,這適用於實體框架4.0 - 更高版本可能有略微不同的EDMX結構(我不確定),因此可能需要修改代碼以解釋這一點。

public class Transform 
{ 
    public static string Standard(string initial, IEnumerable<string> eliminations = null) 
    { 
     Regex re = new Regex(@"(\w+)(\W*?)$", RegexOptions.Compiled); 
     Regex camelSplit = new Regex(@"(?<!^)(?=[A-Z])", RegexOptions.Compiled); 
     return re.Replace(initial, new MatchEvaluator((Match m) => 
     { 
      string name = m.Groups[1].Value; 
      var parts = name.Split('_').AsEnumerable(); 
      if (parts.Count() == 1 && IsMixedCase(name)) 
      { 
       string result = string.Concat(camelSplit.Split(name).Except(eliminations, StringComparer.CurrentCultureIgnoreCase)); 
       return result + m.Groups[2]; 
      } 
      else 
      { 
       parts = parts.Select(s => CultureInfo.CurrentCulture.TextInfo.ToTitleCase(s.ToLower())); 
       parts = parts.Except(eliminations, StringComparer.CurrentCultureIgnoreCase); 
       return string.Concat(parts) + m.Groups[2]; 
      } 
     })); 
    } 

    public static bool IsMixedCase(string name) 
    { 
     int lower = 0, total = 0; 
     for (int i = 0; i < name.Length; i++) 
     { 
      if (char.IsLower(name, i)) lower++; 
      if (char.IsLetter(name, i)) total++; 
     } 
     return lower != 0 && lower != total; 
    } 

} 

現在你可以在Main方法寫一點點代碼,可以接受的參數(除了這將是文件名的第一個),並以後將它們傳遞到eliminations參數;這些可能是需要從名稱中刪除的字符串,在我的情況下是前綴。然後,您可以在調用該工具時從Visual Studio工具界面中指定這些字符串。或者我想你可以硬編碼他們,如果你不關心重複使用該工具:)

+0

這對我來說非常合適,謝謝! – Barn 2011-07-04 14:06:35

+0

對於驗收中的長時間延遲感到抱歉!我的一位同事發現了一個工作解決方案,由於我不再在該公司工作,我完全忘記了他發現的東西。但是你的回答很好,很有效。所以就像你說的那樣:給它信用卡! – 2011-11-21 19:03:27

+0

@Alex我面臨同樣的問題。我只需要在你的解決方案中做一些澄清...我已經創建了一個控制檯應用程序..我應該在哪裏添加上述代碼?那麼如何執行它...這是完全新的...請幫助我 – Xavier 2013-02-25 06:25:13

0

我不知道任何內置剝離表前綴的功能,但可以打開.edmx文件爲XML(使用VS中的Open With)並使用簡單替換來替換前綴。