3

I have a C# Entity which is auto generated via database first:

public partial class Zone
{
    public Guid LocationId {get; set;}
    ...
}

What I need to do is run a function, Process() whenever LocationId is changed. Now normally I would alter the setter and job done, however because this is auto generated via database first, any "manual changes to the file will be overwritten if the code is regenerated."

What would be the best approach here?

The current thinking is to create a new partial class to do something like this:

public partial class Zone
{
    private Guid _pendingLocationId
    public Guid PendingLocationId {
      get { return _pendingLocationId }
      set { 
        Guid updatedLocation = Process(value) ?? value;
        _pendingLocationId = updatedLocation;
        locationId = updatedLocation;
      }
    }
}

Just a note; the unfortunate reality is that there is probably zero chance of us integrating a new framework or library into the application at this stage.


In response to the possible duplicate flag; Unless I have misread, this would require us re-mapping /encapsulating all of our Zone references into a new class, not only pushing this out to all the views, but also editing many linq queries etc. If someone can identify why this would be the preferred solution over my own suggested solve, then please let me know.

Zze
  • 18,229
  • 13
  • 85
  • 118
  • 1
    First, it's very likely that this question will be marked as `opinion based`. Besides that, creating partial class for the generated entities is pretty common approach to deal with this stuff, so I think it's a viable solution for this problem. – Leron Apr 12 '18 at 07:39
  • Possible duplicate: https://stackoverflow.com/questions/14132349/implement-inotifypropertychanged-on-generated-entity-framework-classes – Matt Evans Apr 12 '18 at 07:44
  • Related https://stackoverflow.com/questions/1315621/implementing-inotifypropertychanged-does-a-better-way-exist – Cleptus Apr 12 '18 at 07:45
  • Possible duplicate of [Implement INotifyPropertyChanged on generated Entity Framework classes](https://stackoverflow.com/questions/14132349/implement-inotifypropertychanged-on-generated-entity-framework-classes) – Matt Evans Apr 12 '18 at 07:45
  • _"What I need to do is run a function, Process() whenever LocationId is changed"_ - changed in what sense? By your code? Why do you execute business logic on entities? – CodeCaster Apr 12 '18 at 07:46
  • @CodeCaster Not 100% what you mean. The problem is that there are numerous ways throughout the application to update this value either inherently or directly. Trying to save time by funneling all changes through `Process`. Sorry if that doesn't answer your question. – Zze Apr 12 '18 at 07:52
  • @MatthewEvans Thanks for the links, checking that out now. – Zze Apr 12 '18 at 07:52
  • 1
    @Zze Useful stuff on that link but it doesn't mention PostSharp which I also recommend – Matt Evans Apr 12 '18 at 07:53
  • You can modify T4 template with which your entities are generated, so that it also generates INotifyPropertyChanged implementation for them. – Evk Apr 12 '18 at 08:27

3 Answers3

2

The least intrusive way to do this might be using AOP patterns, for instance, using PostSharp framework: less than 2 lines of code!

[NotifyPropertyChanged]  //<---Add this attributes to the class
public class Zone 
{ 
    public Guid LocationId {get; set;}
    ...

}

To hook the changed event and add your own handler

//Zone instance;
((INotifyPropertyChanged) instance).PropertyChanged += ZoneOnPropertyChanged;

More details can be found here.


Update: the OP mentioned zero chance of integrating other library into the app, I am just curious, don't you use nuget? and what is the reason of this zero chance? In my personal view, you should, rather than NOT, to reinvent the wheels, if there is already a library which does the required features.

If licensing cost is the issue or it is overkill or to heavy to introduce this bulky library just for the sake of the problem, I think Fody, a free open source alternative to PostSharp can be considered. More specifically PropertyChanged.Fody package, which is very standalone, compact and light weight.

David
  • 15,894
  • 22
  • 55
  • 66
  • This would probably solve our issue, just by looking at the above example. Unfortunately, the reality is that there is probably zero chance of us integrating a new framework or library into the application at this stage. I have updated the question to state this as well now. – Zze Apr 12 '18 at 07:57
0

I would suggest using AutoMapper.

You can write another class with the same name and properties (with INPC), but in different namespace. Then, everytime you fetch database, you use Automapper to map the data into your notifiying class and everytime you save data to database you map it back.

That way you only need to change namespaces in code using your class and add code like this into your repository:

var dtos = args.Select(x => Mapper.Map<Zone>(x)).ToList();

Krzysztof Skowronek
  • 2,796
  • 1
  • 13
  • 29
0

Have a business entity mapped to yr database entity (via AutoMapper) and then in your business entity, incorporate the INotifyPropertyChanged interface.

Pseudo code below. This will de-couple your database from business entity and allow independent changes.

namespace DBEntity {
    public class Customer {
         public int Id { get; set; }  ...
    }
}

namespace BizEntity {
    public class Customer : INotifyPropertyChanged {
         private int id;
         public int Id { 
                  get { return this.id } ; 
                  set { 
                       this.id = value; 
                       PropertyChanged(Id...);
                       }
                  }
         NotifyPropertyChanged() {
                    ....
         }

var dbCustomer = GetCustomerFromDB()
var cust = AutoMapper.Mapper.Map<DBEntity.Customer, BizEntity.Customer>(dbCustomer);

// Update the property as per biz requirement
cust.Id = 53656;      // Fires the Notification

Let me know if this helps.
Regarding AutoMapper as a new library, this will be a minimum change and there's no licensing or learning curve required here to allow fast integration.

NitinSingh
  • 2,029
  • 1
  • 15
  • 33