patterncsharpMinor
Entity Framework 6.0.2 - Performance of Auditable Change Tracking Part 1 of 2
Viewed 0 times
auditabletrackingpartperformanceframeworkchangeentity
Problem
This is Part 1 of a question about performance and general best practices. Part 2 is located here. The body of the messages are the same to illustrate their similarity, the difference is the code provided. This one provides the data the text template utilizes, the other provides the logic to generate the code. The focus isn't so much on the template, but the pattern of managing a database that tracks changes across potentially multiple domains.
Another thing I decided I'll be adding: the templates will construct the basic outline of the dialogs through WPF for me. In the case of searching for items within the database, I've already used the data on the entities to generate query builders:
Compared with:
Yields true. While by itself isn't much, it's interesting that I'll be able to enable a user to have a fairly powerful search tool by specifying nested conditions.
I've uploaded a small example which demonstrates the template's use. It's changed quite a lot since the code posted and edited by lol.upvote. It automatically generates the files and folders based off of the context namespace provided in EntityConstants.tt. To preserve space I've removed all binaries, so you might have to fix it in the package manager console when you load the solution.
I'm kind of new to the realm of Database authoring, so I wanted to get some feedback on
Another thing I decided I'll be adding: the templates will construct the basic outline of the dialogs through WPF for me. In the case of searching for items within the database, I've already used the data on the entities to generate query builders:
var recipeQuery = new RecipeQueryData(user);
recipeQuery.CreateIngredientsQueryData();
recipeQuery.IngredientsData.CreateItemQueryData();
recipeQuery.IngredientsData.ItemData.NameCriteria = "t";
recipeQuery.IngredientsData.ItemData.SearchNameType = StringSearchType.Contains;
var recipesWithT2 = RecipeQueryData.ConstructQuery(recipeQuery, fcasCtx.Recipes);Compared with:
var recipesWithT =
(from recipe in fcasCtx.Recipes
from ingredient in recipe.Ingredients
where ingredient.Item.Name.Contains(criteria)
select recipe).Distinct();
Console.WriteLine(recipesWithT.ToString() == recipesWithT2.ToString());Yields true. While by itself isn't much, it's interesting that I'll be able to enable a user to have a fairly powerful search tool by specifying nested conditions.
I've uploaded a small example which demonstrates the template's use. It's changed quite a lot since the code posted and edited by lol.upvote. It automatically generates the files and folders based off of the context namespace provided in EntityConstants.tt. To preserve space I've removed all binaries, so you might have to fix it in the package manager console when you load the solution.
I'm kind of new to the realm of Database authoring, so I wanted to get some feedback on
Solution
I'm not familiar with template coding but I could follow this script all along, except this one-liner:
Doesn't parse in my poor little fried brain. I couldn't figure out where the
I need to break it down to see what it does:
How about at least putting the arguments in order?
If it's possible, I'd try to break this into something like 3 lines, be it only for readability.
Minor annoyance, the resulting code seems to have mixed tabs and spaces:
I don't like the redundant
I find this is a very interesting approach, however it's also a very intrusive one: if I understand your code correctly, your entities are being so much more than the regular average POCO out there.
This breaks the Single Responsibility Principle. I believe a decorator would be less intrusive, and more focused - basically compose the functionality rather than inheriting it.
public <# WriteLine(string.Format("{3}{0} {1} {{ get; {2}set; }}", string.Format("{0}{1}", property.Value.DataType, (nullableTypes.Contains(property.Value.DataType) && (property.Value.Requirements & ER_REQUIRED) != ER_REQUIRED) ? "?" : string.Empty), property.Key, ((property.Value.Requirements & ER_NOTTRACKED) == ER_NOTTRACKED) ? string.Empty : "protected ", targetEnt != null ? "virtual " : string.Empty));Doesn't parse in my poor little fried brain. I couldn't figure out where the
protected was going to end up.I need to break it down to see what it does:
WriteLine(
string.Format("{3}{0} {1} {{ get; {2}set; }}",
string.Format("{0}{1}",
property.Value.DataType,
(nullableTypes.Contains(property.Value.DataType)
&& (property.Value.Requirements & ER_REQUIRED) != ER_REQUIRED)
? "?"
: string.Empty),
property.Key,
((property.Value.Requirements & ER_NOTTRACKED) == ER_NOTTRACKED)
? string.Empty
: "protected ",
targetEnt != null
? "virtual "
: string.Empty));How about at least putting the arguments in order?
WriteLine(
string.Format("{0}{1} {2} {{ get; {3}set; }}",
targetEnt != null
? "virtual "
: string.Empty
string.Format("{0}{1}",
property.Value.DataType,
(nullableTypes.Contains(property.Value.DataType)
&& (property.Value.Requirements & ER_REQUIRED) != ER_REQUIRED)
? "?"
: string.Empty),
property.Key,
((property.Value.Requirements & ER_NOTTRACKED) == ER_NOTTRACKED)
? string.Empty
: "protected "));If it's possible, I'd try to break this into something like 3 lines, be it only for readability.
Minor annoyance, the resulting code seems to have mixed tabs and spaces:
I don't like the redundant
this qualifier sprinkled everywhere, but the code is very consistent about it, so it's only down to personal preference here.I find this is a very interesting approach, however it's also a very intrusive one: if I understand your code correctly, your entities are being so much more than the regular average POCO out there.
This breaks the Single Responsibility Principle. I believe a decorator would be less intrusive, and more focused - basically compose the functionality rather than inheriting it.
Code Snippets
public <# WriteLine(string.Format("{3}{0} {1} {{ get; {2}set; }}", string.Format("{0}{1}", property.Value.DataType, (nullableTypes.Contains(property.Value.DataType) && (property.Value.Requirements & ER_REQUIRED) != ER_REQUIRED) ? "?" : string.Empty), property.Key, ((property.Value.Requirements & ER_NOTTRACKED) == ER_NOTTRACKED) ? string.Empty : "protected ", targetEnt != null ? "virtual " : string.Empty));WriteLine(
string.Format("{3}{0} {1} {{ get; {2}set; }}",
string.Format("{0}{1}",
property.Value.DataType,
(nullableTypes.Contains(property.Value.DataType)
&& (property.Value.Requirements & ER_REQUIRED) != ER_REQUIRED)
? "?"
: string.Empty),
property.Key,
((property.Value.Requirements & ER_NOTTRACKED) == ER_NOTTRACKED)
? string.Empty
: "protected ",
targetEnt != null
? "virtual "
: string.Empty));WriteLine(
string.Format("{0}{1} {2} {{ get; {3}set; }}",
targetEnt != null
? "virtual "
: string.Empty
string.Format("{0}{1}",
property.Value.DataType,
(nullableTypes.Contains(property.Value.DataType)
&& (property.Value.Requirements & ER_REQUIRED) != ER_REQUIRED)
? "?"
: string.Empty),
property.Key,
((property.Value.Requirements & ER_NOTTRACKED) == ER_NOTTRACKED)
? string.Empty
: "protected "));Context
StackExchange Code Review Q#41796, answer score: 2
Revisions (0)
No revisions yet.