EF4 Strip表前缀导入 [英] EF4 Strip table prefixes on import

查看:117
本文介绍了EF4 Strip表前缀导入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试自动重命名表名,以剥离EF4中的前导前缀。我知道它可以在GUI中完成,但是,我公司在Visio中创建了DB模式,并使用它在SQL中创建数据库创建脚本。我们经常这样做,有时候会有很多表,所以使用GUI不是一个想法的解决方案。

I am attempting to have table names automatically renamed to strip off a leading prefix in EF4. I know it can be done in the GUI, however, my company created the DB schema in Visio and use that to create the DB creation script in SQL. We do this often, and sometimes have a lot of tables, so using the GUI is not an idea solution.

有没有想修改.edmx上的属性文件从数据库表中删除定义的前缀,所以Entity类是我们希望的方式?

Is there a want to modify the properties on the .edmx file to strip off a defined prefix from the DB table so the Entity class is how we desire it?

推荐答案

最简单的解决方案想到的是制作一个新的控制台应用程序,它将edmx文件中的所有内容重命名为低级工作;应用程序可以添加到Visual Studio(添加外部工具)的工具菜单中,其中arguments= $(ItemPath),'initial directory'= $(ItemDir),'prompt for arguments'= true和'use output window' = true,则可以使用EDMX文件执行。在我们的例子中,除了剥离前缀之外,我们还需要使用下划线并将其转换为骆驼案例(将下划线解释为单词分隔符)。

The simplest solution we came up with was to make a new console application that did the low level work of renaming everything in the edmx file; the application can be added to the tools menu of Visual Studio (add external tool) with 'arguments' = $(ItemPath), 'initial directory' = $(ItemDir), 'prompt for arguments' = true and 'use output window' = true, then can be executed with the EDMX file selected. In our case, we needed to strip underscores and transform the names to camel case (interpreting the underscore as a word separator), in addition to stripping the prefix.

因为它写得太糟糕了,所以没有其余的代码(像Transform.Standard方法,错误处理和剥离附加参数),因为晚上太晚了重构:P;但是很容易将第一个参数之后的其余参数解释为从名称中删除的字符串等等 - 这个主要代码只是关于EDMX文件所需的修改。如果您使用VS作为外部工具,您可以在参数中的$(ItemPath)后面指定其余的字符串。

I'll omit the rest of the code (like the Transform.Standard method, error handling and the stripping of additional parameters) because it's too badly written to share and it's too late at night for refactoring :P; but it's easy enough to interpret the rest of the arguments after the first as strings to be stripped from names and so on - this main code is only about the modifications needed on the EDMX file. In case you use this as an External Tool from VS, you can specify the rest of the strings after $(ItemPath) in 'arguments'.

请注意, t测试广泛,并且可能还有其他EDMX文件中的其他信息,我们未能说明(但我怀疑);还有,我从网上的其他地方得到了代码的一部分,但没有写下什么地方,很抱歉!应该给予信用。此外,自然,这将是一个更好的VS2010的扩展,但我根本没有时间去做 - 如果你链接到某个地方,我会用它代替;)

Please note this wasn't tested extensively, and there may be additional information in other EDMX files that we failed to account for (but I doubt it); also, I got part of the code from somewhere else on the net but failed to write down where exactly, so sorry! Credit should have been given accordingly. Also, naturally this would have been much better as an extension for VS2010, but I simply did not have the time to do it - if you do link it somewhere and I'll use that instead ;)

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类。此外,请注意,这适用于Entity Framework 4.0 - 更高版本的EDMX结构可能略有不同(我不确定),因此代码可能需要修改才能解决。

adding the Transform class used by the code above. Also, please note that this works for Entity Framework 4.0 - later versions might have slightly different EDMX structure (I'm not sure) so the code might need to be modified to account for that.

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方法中可以使用参数的更多代码(除了第一个将是该文件的名称之外),并将它们传递给 offsinations 参数;这些可能是需要从名称中删除的字符串,在我的情况下是前缀。然后,当调用该工具时,您可以从visual studio工具界面指定这些字符串。或者我想你可以只是硬编码,如果你不关心重复使用这个工具:)

Now you could write a little bit more code in the Main method that could take the arguments (except the first one which will be the name of the file) and pass them onward to the eliminations parameter; these could be strings that need to be erased from the names, in my case the prefixes. You can then specify these strings from the visual studio tools interface when invoking the tool. Or I suppose you can just hardcode them if you don't care that much about reusing the tool :)

这篇关于EF4 Strip表前缀导入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆