Globally Tag EF Core Queries with ".TagWithCallSite()" - entity-framework-core

With the release of the .TagWithCallSite() method in EF Core 6.0 I was wondering if there is a way to apply this globally on every query run via a DbContext in some way?
It would be much better to apply this across the whole project without having to put it on each query individually.

TagWithCallSite accepts parameters marked with CallerFilePathAttribute and CallerLineNumberAttribute which are filled in by compiler (or manually if needed) during build so it is impossible to set up globally.

No, you cant't do that.
When you explicitly define TagWithCallSite(), complier automatically fills default parameters filePath and lineNumber. It is not possible to define that for all queries because compiler do not store such information in Expression Tree.

Related

Colliding aspects in postsharp

I am using the PostSharp solution for INotifyPropertyChanged by decorating my business classes with the [NotifyPropertyChanged] attribute.
All works fine.
Now I wrote a custom aspect that handles property changes so that I get some custom flags set when some special properties change. This aspects is named [HandlePropertyChanged] and works when used alone.
Now I try to use both aspects in combination. As I read on the PostSharp page I can manually order them to ensure a fixed order by using
[NotifyPropertyChanged(AspectPriority = 0)]
[HandlePropertyChanged(AspectPriority = 1)]
In this case, I can build my solution, but because "NotifyPropertyChanged" runs before "HandlePropertyChanged", the changes on my properties are already done and the custom logic does not run correctly.
If I try this
[HandlePropertyChanged(AspectPriority = 0)]
[NotifyPropertyChanged(AspectPriority = 1)]
my build fails with the error at the bottm of the text (see below).
Best would be to simply do what NotifyPropertyChanged does in my custom aspect and forget about the PostSharp aspect
Is this possible?
0: Error C:\Source\WAVE\WAVE.Data.Contracts\Entities\Base\EntityBase.cs (17,16) PS0115: Conflicting aspects on "TopMotive.WAVE.Data.Contracts.Entities.Base.EntityBase`1": according to aspect dependencies, transformation "Instantiation of aspect PostSharp.Patterns.Model.NotifyPropertyChangedAttribute" should be located both before and after transformation "Instantiates binding collection for field "PostSharp.Patterns.Model.NotifyPropertyChangedAttribute/LocationBindings".".
This bug is fixed in PostSharp 5.0.52 and PostSharp 6.0.16 RC.
Try superior and free alternative: Stepen Cleary's Calculated Properties.
https://github.com/StephenCleary/CalculatedProperties/blob/master/README.md
I used both in production and found it to be far better than PostSharp's aspect.
Also from PostSharp docs:
"If a property getter calls a virtual method from its class or a delegate, or references a property of another object (without using canonical form this.field.Property), PostSharp will generate an error because it cannot resolve such a dependency at build time. The same limitations apply when your property getter contains complex data flows, such as loops, or calls to methods (except property getters) of other classes.
When this happens, you can either refactor your code so that it can be automatically analyzed by PostSharp, or you can take over the responsibility for analyzing the code"
None of those limitations apply to Calculated Properties. It can do loops, virtual methods, LINQ to objects, basically any runtime dependencies that you can imagine doesn't matter how indirect. Dependency graph rewires itself at runtime and just works without any ceremony. They are also fast.

What is the purpose of MigrateDatabaseToLatestVersion useSuppliedContext = false?

Something I ran into recently.
I have a project which dynamically generates connection strings and I'm trying to use MigrateDatabaseToLatestVersion on the context that wraps these. Every time I would do this I would see my dynamic db not be created, but instead the db on my default constructor connection string (used for testing) migrated over and over.
After digging through the EF migrations source code I find that MigrateDatabaseToLatestVersion has a constructor
// Summary:
// Initializes a new instance of the MigrateDatabaseToLatestVersion class specifying
// whether to use the connection information from the context that triggered initialization
// to perform the migration.
//
// Parameters:
// useSuppliedContext:
// If set to true the initializer is run using the connection information from the
// context that triggered initialization. Otherwise, the connection information
// will be taken from a context constructed using the default constructor or registered
// factory if applicable.
public MigrateDatabaseToLatestVersion(bool useSuppliedContext);
Not being flippant but what is the reason why you would want to ever migrate the context that is not the one that is being migrated? Why is that the default? Does anyone have any insight into the thinking here?
I want to know the answer to this question myself. I do not know why the context was designed that way. However, I can venture a guess as to why the current default is useSuppliedContext=false.
I decompiled the first version of EntityFramework to include migration support, EntityFramework-4.3.0, because I suspect that the default behavior is for backwards compatibility purposes. I looked at the decompiled implementation of IDatabaseInitializer<TContext>.InitializeDatabase(TContext context) in MigrateDatabaseToLatestVersion. Guess what? In EntityFramework-4.3.0, the context parameter of that method is completely ignored. So it can’t possibly respond to explicitly-provided connection parameters/settings because those are only accessible through that context variable.
It looks like support for respecting context was added in EntityFramework-6.1.1. Prior to that, your only option was to pass a connection string to MigrateDatabaseToLatestVersion’s constructor. I think this would have prevented you from using the same DbContext type for different backends in the same process. I bet that the new feature of respecting the context (and behaving correctly, IMO) would not have been accepted into EntityFramework if it was enabled by default because that would change behavior which stable projects may be relying on and otherwise prevent projects from adopting it.
The exact reasoning is actually given as a comment in commit 777a7a77a740c75d1828eb53332ab3d31ebbcfa3 by Rowan Miller:
Also swapping the new useSuppliedContext parameter on MigrateDatabaseToLatestVersion`.cs to be false by default since we are going to be shipping this change in a patch release.

Possibility of an LLVM LTO Pass plugin?

I was wondering if it's currently possible to have an 'external' (.so/.dylib) LLVM plugin (module) pass scheduled at LTO time? The reason for wanting this is a inter-modular optimization I want to add.
I also found this topic; How to write a custom intermodular pass in LLVM?
But a separate tool is not an option for me.
Thanks
I think the most helpful thing here might be to understand how passes are run and what the state of the code is during LTO.
First of all, when optimization passes are run by the compiler, they are done as a set that has been added to a PassManager. This means that LLVM/Clang, when passed something like -O3 will create a copy of a PassManager and subsequently provide it the set of passes expected to provide O3 level of optimization. This is very different from what you are doing with an external library which must be provided manually and cannot be fit into the pass pipeline normally.
Then we have the state of things when doing LTO. During Link Time Optimization, all of the individual translation units have been consolidated and are now a single Module. This means that an optimization which runs on each function will run on every function in the code base. Similarly, a per-module optimization will run on the full Module and therefor offer Inter-Procedural Analysis/Optimization.
If you're looking to use an Intra-Modular Pass then there is no reason to do this at LTO time and instead you can simply make a ModulePass and run that on each unit.

MEF: Importing on Fields

Is it recommended that we place an Import on a property instead of a field? I tried it on a field and it is working but Resharper is telling me a warning that the field was never initialized.
ReSharper doesn't recognize that MEF will be setting the variable and since there is no guarntee that MEF will be setting the variable (example if it isn't put into a container for example), so it is reasonable for ReSharper to warn about this. You can either ignore it or simply initialize the field to null (or default(T)).
As for whether or not you should use a property or field I think using a field is fine (assuming it is not public). I generally reserve properties for things I want to expose publicly. One special case to consider here is that there are some issues having Imports on private members in low trust scenarios like SL or paritial trust because MEF uses reflection and you cannot use private reflection in some of those scenarios.

Entity Framework - Specify Template when Generating Model

When I'm generating/refreshing my model from the database, how do I specify which template to use?
At the moment, despite having my new template, it still uses the default. Then I have to go in and clear out the contents of 'MyDatabase.Designer.cs', then manually go in to my template and run it.
Surely I can just specify which template my model should use?
At first, you should disable the default code generation. The simplest solution is to clear the Custom Tool property of the model file.
After this just run your template.
There is even simpler way: go to the model Properties and set the Code Generation Strategy property to None.