Всем привет. Есть задача которая вызывала у меня трудности — возможно кто-то уже сталкивался с ней или просто знает решение — тогда плиз поделитесь решением, или хотя бы подскажите куда копать.
задача: есть база, необходимо по ConnectionString автоматически сгенерировать EF модель (классы для таблиц и контекст) моделька должна быть представленна в виде DLL. ключевое слово здесь "Автоматически" т.е. без вмешательства программиста: — на вход дали ConnectionString на выходе получили DLL в которой EF модель (классы+отношения+контекст). еще одним очень важным условием является то, что должна быть возможность кастомизировать генерацию модельки т.е. там по мимо самих классов для таблиц предполагаются еще дополнительные классы.
как это можно сделать руками: — создаем проект, добавляем в него EDMX, к EDMX добавляем T4 шаблон, изменяем его под наши нужды, и компилируем — в результате имеем то что нам нужно. это все работает прекрасно но с одним недостатком — здесь нужен программер который все это делает руками. задача в том чтобы сделать функцию которой на вход передать ConnectionString а на выходе получить DLL.
как я это пытаюсь сделать: написал функцию которая на вход получает ConnectionString, вызывает EdmGen который генерирует csdl, msl, ssdl файлы а так же что самое важное для меня cs, его я компилирую и получаю DLL. в принципе почти то что мне нужно за одним исключением — я не могу в этом процессе кастомизировать генерацию cs кода при помощи T4 а это одно из необходимых условий.
в принципе на данном этапе задача сводиться к следующим вопросам:
1) можно ли генерировать код не прибегая к вызову утилиты EdmGen.exe а используя какой-то API, при этом кастомизируя генерацию кода при помощи T4
2) и если нет, то как кастомизировать генерацию кода которую делает EdmGen.exe при помощи T4 шаблона
может кто посоветует как это сделать, по большому счету мне хотя бы ответ на второй вопрос и это уже решило бы много проблем.
Re: [EntityFramework] Кастомная генерация cs кода в EdmGen.exe
От:
Аноним
Дата:
18.11.12 12:38
Оценка:
Здравствуйте, DashkovAndrey, Вы писали:
DA>1) можно ли генерировать код не прибегая к вызову утилиты EdmGen.exe а используя какой-то API, при этом кастомизируя генерацию кода при помощи T4 DA>2) и если нет, то как кастомизировать генерацию кода которую делает EdmGen.exe при помощи T4 шаблона
DA> может кто посоветует как это сделать, по большому счету мне хотя бы ответ на второй вопрос и это уже решило бы много проблем.
1. можно, EdmGen использует именно API, как именно — лучше всего глянуть рефлектором
2. Т4 шаблон можно использовать в своем приложении, смотреть Runtime Text Template
Re[2]: [EntityFramework] Кастомная генерация cs кода в EdmGen.exe
Парни, я реально ценю желание помочь и я точно не хотел бы оттолкнуть тех кто хочет помочь, но пожалуйста соотносите ответ с проблемой. я написал так много букв для того чтобы не получать вместо ответа что-то в дуже: "а что ты имел ввиду", "а зачем тебе это вообще нужно" или "да можно, а как именно — гугл в помощь".
А>1. можно, EdmGen использует именно API, как именно — лучше всего глянуть рефлектором
я не хочу использовать рефлектор для такого — это должно быть описано и тот кто с этим работал наверняка знает где порчитать — а парсить утилиту рефлетором с такой целью это как по мне не совсем правильно, как по мне. прежде чем взяться за проблему я конечно же погуглил: здесь в частности "The EntityModelCodeGenerator and EdmGen.exe command line tool use the EntityClassGenerator class to generate the source code" по этому я использовал его для генерации
EntityClassGenerator generator = new EntityClassGenerator(LanguageOption.GenerateCSharpCode);
var t = generator.GenerateCode(@"G:\Temp\bozz.csdl",@"G:\Temp\aaa.cs");
в результате я получаю ошибку "The EntityClassGenerator is only for use with EntityFrameworkVersions.Version1 and the schemas provided have newer versions of the Model schema. Consider using EntityCodeGenerator or a template."
А>2. Т4 шаблон можно использовать в своем приложении, смотреть Runtime Text Template
я не сомневаюсь что можно — я сказал что сделал это в обычном режиме когда разрабатываю код, но штука в том что это должно быть сделано не в Design-Time — а в Run-Time. в ссылке которую вы дали я к сожалению не нашел ответ на вопрос: как указать T4 шаблон для кастомизации генерации cs кода в утилиту EdmGen или другую которая генерирует cs код по модели данных из базы.
это же не просто трансформация — там есть свой API который можно удобно использовать — вот пример TT который я использую для кастомизации при разработке в Design-time
<#
CodeGenerationTools code = new CodeGenerationTools(this);
MetadataLoader loader = new MetadataLoader(this);
CodeRegion region = new CodeRegion(this, 1);
MetadataTools ef = new MetadataTools(this);
string inputFile = @"BozzEntities.edmx";
EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
string namespaceName = code.VsNamespaceSuggestion();
EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);
// Write out support code to primary template output file
WriteHeader(fileManager);
BeginNamespace(namespaceName, code);
//WriteCustomObservableCollection();
EndNamespace(namespaceName);
// Emit Entity Types
foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
{
#>
<#
fileManager.StartNewFile(entity.Name + "Activities.cs");
BeginNamespace(namespaceName+".Activities", code);
#>
<#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#>partial class Save<#=code.Escape(entity)#>Activity<#=code.StringBefore(" : ", code.Escape("CodeActivity"))#>
{
// Define an activity input argument of type string
public InArgument<<#=code.Escape(entity)#>> Entity { get; set; }
// If your activity returns a value, derive from CodeActivity<TResult>
// and return the value from the Execute method.
protected override void Execute(CodeActivityContext context)
{
// Obtain the runtime value of the Text input argument
<#=code.Escape(entity)#> entity = context.GetValue(this.Entity);
using (BozzEntities db = new BozzEntities())
{
db.<#=code.Escape(entity)#>.AddObject(entity);
db.SaveChanges();
}
}
}
вопрос не в том можно ли сделать это вообще — а в том как это сделать в частности, в Run-Time )
Re[3]: [EntityFramework] Кастомная генерация cs кода в EdmGen.exe
От:
Аноним
Дата:
18.11.12 14:45
Оценка:
Здравствуйте, DashkovAndrey, Вы писали:
DA>Здравствуйте, Аноним, Вы писали:
DA>Парни, я реально ценю желание помочь и я точно не хотел бы оттолкнуть тех кто хочет помочь, но пожалуйста соотносите ответ с проблемой. я написал так много букв для того чтобы не получать вместо ответа что-то в дуже: "а что ты имел ввиду", "а зачем тебе это вообще нужно" или "да можно, а как именно — гугл в помощь".
DA>вопрос не в том можно ли сделать это вообще — а в том как это сделать в частности, в Run-Time )
т.е. нужен готовый проект? тогда только в понедельник, дома у меня голая ось.
но там не много кодить, можно и самому попробовать.
1. код для генерирации метаданных примерно такой:
var catalogIndex = connectionStr.IndexOf("initial catalog=") + 16;
var catalogLength = connectionStr.IndexOf(';', catalogIndex) - catalogIndex;
var catalog = connectionStr.Substring(catalogIndex, catalogLength);
var storeGenerator = new EntityStoreSchemaGenerator(
"System.Data.SqlClient",
connectionStr,
modelNamespace + ".Store");
storeGenerator.GenerateStoreMetadata(entityFilter);
var modelGenerator = new EntityModelSchemaGenerator(
storeGenerator.EntityContainer,
modelNamespace,
modelNamespace + "Container");
modelGenerator.GenerateForeignKeyProperties = true;
modelGenerator.PluralizationService = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en-US"));
modelGenerator.GenerateMetadata();
2. используя T4 preprocessed template генерируем класс, который в run-time будет генерировать код, который вы сейчас получаете в design-time.
3. этот класс partial, расширяем его кодом из п.1. дальше уже вам виднее, чего там должно быть.
Re[4]: [EntityFramework] Кастомная генерация cs кода в EdmGen.exe
От:
Аноним
Дата:
18.11.12 18:20
Оценка:
Здравствуйте, Аноним, Вы писали:
А>т.е. нужен готовый проект?
ну, на код я даже и не смел надеяться — но если код... то это больше моих ожиданий.
сейчас я сделал эту задачу при помощи командной строки.
1) генерирую при помощи EdmGen файлы : csdl, ssdl, msl — к сожалению он вдобавок генерирует и cs класс который я просто удаляю
2) потом при помощи T4 передавая в качестве параметра csdl генерирую контекс+доменные сущности а потом и тот код что мне нужен.
3) а потом используя csc компилирую это все в DLL
конечно можно написать системный вызов этих утилит из кода, но хотелось бы это все сделать через API в коде — это было бы счастье
Вам огромное спасибо, что не прошли мимо и помогаете с решением.