EF4 Полосные префиксы таблиц при импорте - PullRequest
2 голосов
/ 20 ноября 2010

Я пытаюсь автоматически переименовать имена таблиц, чтобы убрать ведущий префикс в EF4. Я знаю, что это можно сделать в графическом интерфейсе, однако моя компания создала схему БД в Visio и использовала ее для создания сценария создания БД в SQL. Мы делаем это часто, а иногда и много таблиц, поэтому использование графического интерфейса не является идеальным решением.

Есть ли способ изменить свойства файла .edmx, чтобы убрать определенный префикс из таблицы БД, чтобы класс Entity был таким, каким мы его хотим?

Ответы [ 2 ]

7 голосов
/ 22 ноября 2010

Самое простое решение, которое мы придумали, - это создать новое консольное приложение, которое выполняло низкоуровневую работу по переименованию всего в файле edmx; приложение можно добавить в меню инструментов Visual Studio (добавить внешний инструмент) с помощью «arguments» = $ (ItemPath), «начального каталога» = $ (ItemDir), «подсказки для аргументов» = true и «использовать окно вывода» = true, тогда может выполняться с выбранным файлом EDMX. В нашем случае нам нужно было убрать подчеркивания и преобразовать имена в регистр верблюдов (интерпретируя подчеркивание как разделитель слов), в дополнение к удалению префикса.

Я опущу оставшуюся часть кода (например, метод Transform.Standard, обработку ошибок и удаление дополнительных параметров), потому что он слишком плохо написан для совместного использования и слишком поздно ночью для рефакторинга: P; но достаточно просто интерпретировать остальные аргументы после первого как строки, которые нужно удалить из имен и т. д. - этот основной код касается только изменений, необходимых для файла EDMX. Если вы используете это как внешний инструмент от VS, вы можете указать остальные строки после $ (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, используемого приведенным выше кодом. Кроме того, обратите внимание, что это работает для Entity Framework 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 голосов
/ 21 ноября 2010

Я не знаю ни одной встроенной функции для удаления префиксов таблиц, но вы можете открыть файл .edmx в формате XML (используйте Open With в VS) и использовать простую замену, чтобы заменить префикс ничем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...