PropertyChange at DbContext in EF 6

Topics: EF Designer, EF Runtime, General
Mar 27 at 2:01 PM
Edited Mar 28 at 11:53 AM
Hello!

We migrated from EF 5 ObjectContext to EF 6 DbContext and changed a lot(!) of code.

(We're using Database first approach + EDMX-graphical designer)

In ObjectContext we used this, to subscribe the modifications:

customer.PropertyChanged += new PropertyChangedEventHandler(customer_PropertyChanged);

But in DbContext, PropertyChanged doesn't exist! So we tried to generate a partial class of customer and implemented ": INotifyPropertyChanged". After this, the "PropertyChanged += " above can be used, but doesn't work, because in the partial class we can't change the getter and setters of the single fields which are defined automatically by the EMDX-Designer.

(In ObjectContext the PropertyChanged was fired when one of the fields from the EntityClass was changed in the WPF-Form or via code. Now we need the same behaviour.)

There are a lot of approaches, but all fails:

http://stackoverflow.com/questions/11262816/partial-class-entity-framework-propertychanged
They suggest: "public partial class Product: EntityObject"
But than you get an error while connecting: 'The type 'Product' was not associated. Ensure, that the type is....and not inherits from 'EntityObject''.
http://stackoverflow.com/questions/20144103/update-entity-framework-property-when-different-property-in-model-is-changed
They suggest: "public Product() {...}"
Under ObjectContext it was possible to create a constructor in the partial class, but in DbContext you get an error: 'The typ 'Product' is defining a member named 'Product' with the same parameter-types' --- (I hate this too, because sometimes I want to set some field-values at initialization. Now its not possible!?)
And here you can read, there is another possibility than PropertyChange:
http://stackoverflow.com/questions/7767218/why-does-the-binding-update-without-implementing-inotifypropertychanged
But it seems, this only detect changes from the WPF-Form, not the changes made by code directly?
So what's your suggestion to:
  • catch the PropertyChange if any fields of a 'Entity'-Class has changed? and
  • ...which detects the WPF-changes and the changes made by code and
  • ...which can be subscribed easily like: customer.PropertyChanged += new PropertyChangedEventHandler(customer_PropertyChanged); and
  • ...which will not be changed in some years again
Is there somewhere who can help?

Thank you very much!

Best regards
Developer
Mar 28 at 7:10 PM
@leveloper If you have an existing app that uses ObjectContext and you don’t want to change all your code, then consider using the code generation templates here: http://visualstudiogallery.msdn.microsoft.com/66612113-549c-4a9e-a14a-f629ceb3f89a. These templates will generate an ObjectContext and entities derived from EntityObject that work with EF6.

To implement INotifyPropertyChanged consider updating the DbContext T4 templates to generate the appropriate code in your entities. The basic idea is covered here: http://stackoverflow.com/questions/11010718/how-to-get-property-change-notifications-with-ef-4-x-dbcontext-generator. The answer was for EF 4.x, but nothing fundamental has changed since then, so the general ideas should still apply even if slight tweaks are needed in the template changes.

If you are doing WPF data binding, then you may want to look at http://msdn.microsoft.com/en-us/data/jj574514 for common patterns when using EF DbContext for this. This documentation also contains general information about editing templates.

Thanks,
Arthur
Mar 31 at 3:16 PM
Hi Arthur!

Thank you very much for your different approaches!

ObjectContext: After I spend much time to shift to DbContext, first I want to try PropertyChange in DbContext. Another reason is, that at the website you are posted, there are many comments, that it's not working correctly; so I'am a little bit deterred.

T4-Templates changing:
I don't like to change the templates, because after every entity framework-update I have to do it again. But still I tried this way and I got a couple of errors without thighter informations. (Additionally, the newer templates looks a little bit different, which may cause the problem?)
1.) Which approach is the right? I tried the first one and considered the comment at the end of the page.
2.) It's possible for your team, in the new release of the Entity Framework, to insert these lines automatically in the template, when a special switch will be set? So for many developers this might be a very easy and fast way to use PropertyChanged. Second, after updating to a newer T4-Template, no developer has to care about these modifications again.
The third link also doesn't solves the PropertyChange-Problem for us, but now I considered the following solution:
  • to copy the automatically generated code from all tables(=entities) (e. g. customer.cs) out ouf the MyModel.tt in an own cs-file and
  • to add the key-data-annotations to the necessary fields
  • to copy the automatically generated Db-context out of the MyModel.Context.cs in an own cs-file.
3.) After this, it's possible to run the application in Code-First without further modifications?
Another way D:
First, we could create a ViewModelBase, which implements INotifyPropertyChanged. After that, we could define all tables(=entities) (e. g. customer) as a partial classes again and could implement the :ViewModelBase.
4.) Is it possible in each self defined partial table(=entity-class) (e. g. customer) to implement a behaviour that a field-modification of any field raises the PropertyChange?
Another way E:
When I copy the automatically generated customer.cs from the tt-file into my own cs-file and comment it out, the program is still running. After that, I can extend the customer.cs so that the PropertyChanged is rising, while adding it to each field-setter. Then it works.
5.) After I do this, EF asks, the table was modified outside the Generator and if it has to be loaded again. Whatever I click: no or yes, it will be generated again. (After clicking yes once, the Messagebox doesn't asks again?) Why will the code created when I click "no"? / How will I see this Messagebox in future again?
6.) Can you change the behaviour of the EntityFramework in future, that the cs-file for this class (e. g. customer.cs) is not created again, when it's commented out completely?
Thank you very much!

It is most appreciated.

Best regards,
leveloper
Developer
Apr 2 at 11:05 PM
@leveloper If you want to have property change notifications in POCO entities when using Database First, then I think the best approach is to modify the T4 templates. It's unlikely that we will change the templates to have this built in because it is something that is not needed by many people. In general we try to keep the entities generated very simple and also keep the templates simple so that people can more easily edit them to add whatever they need. We have considered releasing multiple templates for different purposes or adding customization points to the templates but as of now this is not high on our priority list of things to do.

For question #3 the answer is, in general, no. The correct thing to do for Code First development is to use the EF 6.1 tooling to scaffold a Code First context and entities. The scaffolded code will include appropriate Code First mapping information which may be missing when using the approach you outlined. See http://blogs.msdn.com/b/adonet/archive/2014/03/17/ef6-1-0-rtm-available.aspx for details.

For #4 I don't know of any reasonable way to do this.

For #5 and #6 it is important to understand that the EDMX file used by the designer is the source of truth and is the artifact that should be edited. The generated classes are truly auto-generated and will always be automatically re-generated when the EDMX changes. The message box you mention is just Visual Studio asking if you want to see the re-generated file. Whether or not you look at it doesn't change the fact that is has been re-generated and will continue to be re-generated.

On the other hand, when you reverse engineer to Code First using the EF 6.1. tooling the code is generated once and then you are free to edit it. It will never be automatically re-generated again. For that you would need to run the reverse engineering wizard again. So is this respect reverse engineering to Code First may be a better option for you than Database First.
May 27 at 3:46 PM
The best approach would be to allow adding the event via the designer per property or per model, and not ask users to modify T4.
Jul 10 at 12:32 PM
Edited Jul 10 at 12:37 PM
Hi Arthur!

I'm sorry for my very late answer. We had too much work after a longer illness. In the meantime we tried all ways and decided:

____The migration from ObjectContext to DbContext ist too much effort for this big project. There are to much snares and too much changes necessary. (Thousand lines of program code.)

A big thing is, that PropertyChanged cannot easily and comfortable used in DbContext. So after all, we shifted back to ObjectContext and WILL STILL USE OBJECTCONTEXT IN FUTURE.____

Thank you for your link to:

EF 6.x EntityObject Generator for C#
http://visualstudiogallery.msdn.microsoft.com/66612113-549c-4a9e-a14a-f629ceb3f89a


This works without troubles. Only thing is an error code, after adding tables in the graphical EDMX-Designer. The error is: "Exception from the type 'System.Runtime.InteropServices.COMException' while refreshing over the database. The exception is: There still exists a file or folder with the name "MyModel.Context.tt". Give the element, which has to be added, a unique name or delete the element before." (Translated to english)

After ignoring this message the program runs well.

(After expanding 'MyModel.edmx' we see only this two files: MyModel.Context.tt and MyModel.Designer.cs.)

Please integrate the EntityObject Generator in future in the nuget-Package again and create a possibility to switch between ObjectContext and DbContext comfortably. For us and many others, the ObjectContext is the easier way to create programs.

There are now 26113 downloads from the EF 6.x EntityObject Generator for C#, so you see, there are a lot of programmers who using ObjectContext.

So thank you again very much!