编辑T4模板不会更改模型上生成的代码

时间:2018-12-06 11:10:29

标签: c# visual-studio templates t4 auto-generate

我需要使用数据库优先方法为项目覆盖或替换模型的默认构造函数。经过研究,我发现此答案最适合完成我想要的目标:Override or replace default constructor when using database first approach

因此,不是专家,我去了ProjectModel.edmx,在里面发现了两个扩展名为.tt的文件,它们分别称为 #include <iostream> #include <map> #include <set> #include <iomanip> #include <string> #include <vector> using namespace std; class FoodDrink{ int id; string name; double price; int preparationTime; public: FoodDrink() {}; public: FoodDrink(int id, string name, double price, int preparationTime) { this->id = id; this->name = name; this->price = price; this->preparationTime = preparationTime; } public: int getId() { return id; } public: string getName() { return name; } public: double getPrice() { return price; } public: int getPreparationTime() { return preparationTime; } }; class Menu { static const int SOUP_NUMBER = 4; static const int MAINMEAL_NUMBER = 5; static const int SIDEDISH_NUMBER = 3; static const int DRINK_NUMBER = 4; static const int ALL_MEAL_NUMBER = SOUP_NUMBER + MAINMEAL_NUMBER + SIDEDISH_NUMBER + DRINK_NUMBER; FoodDrink allMeals[ALL_MEAL_NUMBER] = { FoodDrink(0, "Garlic soup", 1.49, 8), FoodDrink(1, "Vegetable soup", 1.59, 10), FoodDrink(2, "Chicken soup", 1.69, 9), FoodDrink(3, "Beef soup", 1.69, 11), FoodDrink(4, "Potato dumplings with sheep cheese", 4.95, 16), FoodDrink(5, "Chicken with niva sauce", 6.75, 19), FoodDrink(6, "Spicy pork ribs", 7.49, 23), FoodDrink(7, "Beef on mushrooms", 8.25, 22), FoodDrink(8, "Vegetable risotto", 4.99, 15), FoodDrink(9, "Chips", 1.79, 7), FoodDrink(10, "Potatos", 1.59, 12), FoodDrink(11, "Rice", 1.49, 11), FoodDrink(12, "Beer", 1.79, 2), FoodDrink(13, "Coca-cola", 1.59, 1), FoodDrink(14, "Orange juice", 1.99, 1), FoodDrink(15, "Mineral watter", 1.39, 1) }; public: FoodDrink getMeal(int id) { return allMeals[id]; } public:void showMenu() { cout << "MENU" << endl; cout << setw(5) << "Id" << setw(40) << "Meal/drink" << setw(15) << "Price(eur)" << setw(20) << "Preparation(min)" << endl; cout << "---------------------------------------------------------------------------" << endl; cout << "Soups" << endl; for (auto i = 0; i < ALL_MEAL_NUMBER; i++) { if (i == SOUP_NUMBER) cout << "Main meals" << endl; else if (i == SOUP_NUMBER + MAINMEAL_NUMBER) cout << "Side dishes" << endl; else if (i == SOUP_NUMBER + MAINMEAL_NUMBER + SIDEDISH_NUMBER) cout << "Drinks" << endl; cout << setw(5) << allMeals[i].getId() << setw(40) << allMeals[i].getName() << setw(13) << allMeals[i].getPrice() << setw(12) << allMeals[i].getPreparationTime() << endl; } } }; class Order { vector<FoodDrink> order; bool isPaid = false; Menu menu; public: void setOrder(int id){ order.push_back(menu.getMeal(id)); } public: double calculateOrder() { double total = 0; for (unsigned int i = 0; i < order.size(); i++) { total += order[i].getPrice(); } return total; } public: void pay() { isPaid = true; } }; class Table { Order order; bool occupied = false; public: Order getOrder() { return order; } public: bool isOccupied() { return occupied; } public: bool setOccupied(bool occupied) { this->occupied = true; } }; class Restaurant { Menu menu; static const int NUMBER_TABLES = 10; set<int> occupiedTables; Table tables[NUMBER_TABLES]; public: Restaurant() { for (int i = 0; i < NUMBER_TABLES; i++) { tables[i] = Table(); } } public: Table getTable(int number) { return tables[number]; } public:bool newCustomer(int tableNumber) { if (tableNumber < 1 || tableNumber > NUMBER_TABLES || occupiedTables.find(tableNumber) != occupiedTables.end()) return false; tables[tableNumber].setOccupied(true); occupiedTables.insert(tableNumber); return true; } public:bool leaveCustomer(int tableNumber) { if (tableNumber < 1 || tableNumber > NUMBER_TABLES || occupiedTables.find(tableNumber) == occupiedTables.end()) return false; tables[tableNumber].setOccupied(false); occupiedTables.erase(tableNumber); return true; } public: void addToOrder(int tableNumber, int meal_id, int pieces = 1) { for (int i = 0; i < pieces; i++) { tables[tableNumber].getOrder().setOrder(meal_id); } } }; int main() { Menu m; Restaurant r; r.newCustomer(1); r.addToOrder(1, 5); r.addToOrder(1, 12, 2); cout << r.getTable(1).getOrder().calculateOrder() << endl; } {{1 }} ,所以我认为我需要编辑第二个。

试图了解它是如何工作的,我发现了一段代码似乎可以生成类的构造函数:

ProjectModel.Context.tt

我添加了第25行和第28行,只是为了通过调用Init()生成模型,并在此之后声明方法。

现在,我进入显示数据库图的 ProjectModel.tt ,右键单击该图并运行从数据库更新模型... 在菜单中。然后,我进入刷新标签并突出显示表格,然后单击完成。我原以为新生成的文件将与此类似:

 1 <#
 2     var complexProperties = typeMapper.GetComplexProperties(complex);
 3     var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(complex);
 4 
 5     if (propertiesWithDefaultValues.Any() || complexProperties.Any())
 6     {
 7 #>
 8     public <#=code.Escape(complex)#>()
 9     {
10 <#
11         foreach (var edmProperty in propertiesWithDefaultValues)
12         {
13 #>
14         this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
15 <#
16         }
17 
18         foreach (var complexProperty in complexProperties)
19         {
20 #>
21         this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
22 <#
23         }
24 #>
25      Init();
26     }
27 
28     partial void Init();
29 
30 <#
31     }

但是它不起作用,我想知道是否需要做其他事情,或者是否正在编辑正确的文件。任何指导将不胜感激。

1 个答案:

答案 0 :(得分:1)

您的更改在模板的复杂类型部分中。注意:

 5     if (propertiesWithDefaultValues.Any() || complexProperties.Any())
 6     {
 7 #>
 8     public <#=code.Escape(complex)#>()
 9     {
10 <#

查找实体的迭代,然后在此处进行编辑:

foreach (var entity in typeMapper.GetItemsToGenerate<EntityType>(itemCollection))
{
    fileManager.StartNewFile(entity.Name + ".cs");
    BeginNamespace(code);
#>
<#=codeStringGenerator.UsingDirectives(inHeader: false)#> // This may be slightly different based on version of EF, but you get the idea
<#=codeStringGenerator.EntityClassOpening(entity)#>
{
<#
    var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(entity);
    var collectionNavigationProperties = typeMapper.GetCollectionNavigationProperties(entity);
    var complexProperties = typeMapper.GetComplexProperties(entity);

    if (propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() || complexProperties.Any())
    {
#>
    public <#=code.Escape(entity)#>()
    {
// ... much later
        foreach (var complexProperty in complexProperties)
        {
#>
        this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
<#
        }
#>
    }
    Init();
}
partial void Init();