Tracking which entity properties have changed The 2019 Stack Overflow Developer Survey Results Are InDealing with Entity Framework's lack of enum supportEntity Framework 6.0.2 - Performance of Auditable Change Tracking Part 2 of 2Model Design for MVC4 Applications using Entity Framework Code FirstInsert Model object effectively using entity framworkObject to object mapping verification - is this extension method useful?Indexed Properties in C#Tracking Entity Changes (not EF)Setting Entity Framework up for successWeb-app for tracking containersImmutable type updater using a special constructor

Spanish for "widget"

If a poisoned arrow's piercing damage is reduced to 0, do you still get poisoned?

Extreme, unacceptable situation and I can't attend work tomorrow morning

What is a mixture ratio of propellant?

How can I fix this gap between bookcases I made?

Does light intensity oscillate really fast since it is a wave?

Where to refill my bottle in India?

I looked up a future colleague on LinkedIn before I started a job. I told my colleague about it and he seemed surprised. Should I apologize?

Should I use my personal or workplace e-mail when registering to external websites for work purpose?

In microwave frequencies, do you use a circulator when you need a (near) perfect diode?

Why is my p-value correlated to difference between means in two sample tests?

Why could you hear an Amstrad CPC working?

Idiomatic way to prevent slicing?

Can distinct morphisms between curves induce the same morphism on singular cohomology?

How can I create a character who can assume the widest possible range of creature sizes?

What are the motivations for publishing new editions of an existing textbook, beyond new discoveries in a field?

How to manage monthly salary

What is the steepest angle that a canal can be traversable without locks?

What is the best strategy for white in this position?

Is "plugging out" electronic devices an American expression?

Why Did Howard Stark Use All The Vibranium They Had On A Prototype Shield?

Limit the amount of RAM Mathematica may access?

It's possible to achieve negative score?

How to answer pointed "are you quitting" questioning when I don't want them to suspect



Tracking which entity properties have changed



The 2019 Stack Overflow Developer Survey Results Are InDealing with Entity Framework's lack of enum supportEntity Framework 6.0.2 - Performance of Auditable Change Tracking Part 2 of 2Model Design for MVC4 Applications using Entity Framework Code FirstInsert Model object effectively using entity framworkObject to object mapping verification - is this extension method useful?Indexed Properties in C#Tracking Entity Changes (not EF)Setting Entity Framework up for successWeb-app for tracking containersImmutable type updater using a special constructor



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








2












$begingroup$


There are a number of topics pertaining to entity change tracking. All the ones I've seen involve either 1) notifying when a property has changed or 2) merely determining whether or not an entity is dirty.



My goal is quite different. I wrote a mini-repository framework that generates SQL for inserts, selects, updates, and deletes. Updates are particularly tricky because the framework needs to support partial updates. To do this, you have to know which properties have changed and only generate the update SQL for those specific fields. Otherwise, you run the risk of overwriting existing data with nulls or default values unless you load the original entity from the database prior to the update.



Take this person class as an example:



public class Person

public string FirstName get; set;

public string LastName get; set;

public DateTime DateOfBirth get; set;



Quite a bit of boilerplate code would be required to allow it to track its own property changes. Here's an example (leaving LastName and DateOfBirth alone for brevity):



public class Person

HashSet<string> ChangedProperties =
new HashSet<string>(StringComparer.OrdinalIgnoreCase);

string _FirstName = null;
public string FirstName

get return _FirstName;
set

ChangedProperties.Add(nameof(FirstName));
_FirstName = value;



public string LastName get; set;

public DateTime DateOfBirth get; set;

public string[] GetChangedProperties()

return ChangedProperties.ToArray();




Imagine having to do this for 50 properties or more (some of the classes I work with have 90+ properties).



So I came up with a special tracking class that uses generics and expressions to encapsulate all of that boilerplate property code. Having actually begun to use it in my application, I've developed a bit of a love/hate relationship with it.



Here's the watered-down version of the class:



public class PropertyChangeTracker<TEntity> where TEntity : class

TEntity Entity = null;
HashSet<PropertyInfo> ChangedProperties = new HashSet<PropertyInfo>();

public PropertyChangeTracker(TEntity Entity)

this.Entity = Entity;


public void Set<TValue>(Expression<Func<TEntity, TValue>> Expression, TValue Value)

var Member = (Expression.Body as MemberExpression).Member as PropertyInfo;

ChangedProperties.Add(Member);

Member.SetValue(Entity, Value);


public PropertyInfo[] GetChangedProperties()

return ChangedProperties.ToArray();




It uses reflection to set the property which is, by many engineer standards, a serious no-no that will result in a Christmas stocking full of coal. My production version of the above code actually uses dynamically-generated delegates using expression trees to set entity properties (I may post that code for review at another time), but this should get you started. So long as you're not using reflection haphazardly within thousands of iterations, it isn't really that bad, especially these days with faster hardware and the accumulation of all the .NET framework optimizations that have taken place since .NET's early days.



So here's how you use the class:



var BobJones = PersonRepo.GetPersonById(100);
var Tracker = new EntityChangeTracker<Person>(BobJones);

Tracker.Set(e => e.LastName, "Jones");
Tracker.Set(e => e.DateOfBirth, new DateTime(1970, 2, 15));


In that example, you load Bob from the database and make a correction to his last name and DOB. The tracking class will track that only those properties have changed. When you go to generate your update, you just do this:



 var Properties = Tracker.GetChangedProperties();

string Sql = $@"
update persontable
set string.Join(", ", Properties.Select(pi => $"pi.Name = :pi.Name").ToArray())
where id = 100";


My framework knows how to get the entity table name and primary key for the where clause, but this shows how the update fields are generated:



update persontable 
set LastName = :LastName, DateOfBirth = :DateOfBirth
where id = 100


You can then parameterize it like this:



 var Parameters = Properties.Select(p => new YourDbParameter(p.Name, p.GetValue(BobJones)));


So about that love/hate relationship I mentioned earlier. Here are the pros/cons to this:



Pros



  • The automation/encapsulation aspect prevents the need to write massive amounts of boilerplate code within your class, especially when you're dealing with a large number of properties. Going from auto-properties to properties with concrete setters and getters that contain tracking logic can increase your class code by as much as 11 lines of code per property.

  • The extraction of the property name from an expression eliminates magic strings, though .NET 4.6.1 now offers the nameof keyword which can mitigate this as shown in my first example.

  • This solution can be retrofitted for use with any existing class without having to convert every auto-property to complex properties with tracking logic.

Cons:



  • In an effort to eliminate boilerplate code within your class, you end up writing a bit more code anyway in the form of a lambda expressions every time you want to track changes to your class, but this is typically only noticeable with VB.NET and its verbose lambda syntax. If you just bite down and write all the tracking code within your class, you can, as Ron Popeil would say, set it and forget it and only have to update the code whenever you need to add a new property.

Overall, I really think the pros outweigh the cons, but want to see if anyone else can find a better way to achieve what I've done here or extol the virtues of another implementation.










share|improve this question











$endgroup$











  • $begingroup$
    Did you consider t4 for auto-generating boilerplate code? You can also either wrap entities in a generated wrapper that tracks changes to the properties or simply store a copy of the originally retrieved entity inside your Tracker. But maybe my real question is why you spend time writing your own ORM these days instead of focusing on your business logic.
    $endgroup$
    – Mattias Åslund
    May 11 '16 at 17:45










  • $begingroup$
    @MattiasÅslund Haven't heard of T4, but will look into it. I also don't want to store a copy of the original entity because that means I have to make a database call to get it and I am a minimalist when it comes to accessing resources. I am not really sure I understand the last question.
    $endgroup$
    – oscilatingcretin
    May 11 '16 at 17:52

















2












$begingroup$


There are a number of topics pertaining to entity change tracking. All the ones I've seen involve either 1) notifying when a property has changed or 2) merely determining whether or not an entity is dirty.



My goal is quite different. I wrote a mini-repository framework that generates SQL for inserts, selects, updates, and deletes. Updates are particularly tricky because the framework needs to support partial updates. To do this, you have to know which properties have changed and only generate the update SQL for those specific fields. Otherwise, you run the risk of overwriting existing data with nulls or default values unless you load the original entity from the database prior to the update.



Take this person class as an example:



public class Person

public string FirstName get; set;

public string LastName get; set;

public DateTime DateOfBirth get; set;



Quite a bit of boilerplate code would be required to allow it to track its own property changes. Here's an example (leaving LastName and DateOfBirth alone for brevity):



public class Person

HashSet<string> ChangedProperties =
new HashSet<string>(StringComparer.OrdinalIgnoreCase);

string _FirstName = null;
public string FirstName

get return _FirstName;
set

ChangedProperties.Add(nameof(FirstName));
_FirstName = value;



public string LastName get; set;

public DateTime DateOfBirth get; set;

public string[] GetChangedProperties()

return ChangedProperties.ToArray();




Imagine having to do this for 50 properties or more (some of the classes I work with have 90+ properties).



So I came up with a special tracking class that uses generics and expressions to encapsulate all of that boilerplate property code. Having actually begun to use it in my application, I've developed a bit of a love/hate relationship with it.



Here's the watered-down version of the class:



public class PropertyChangeTracker<TEntity> where TEntity : class

TEntity Entity = null;
HashSet<PropertyInfo> ChangedProperties = new HashSet<PropertyInfo>();

public PropertyChangeTracker(TEntity Entity)

this.Entity = Entity;


public void Set<TValue>(Expression<Func<TEntity, TValue>> Expression, TValue Value)

var Member = (Expression.Body as MemberExpression).Member as PropertyInfo;

ChangedProperties.Add(Member);

Member.SetValue(Entity, Value);


public PropertyInfo[] GetChangedProperties()

return ChangedProperties.ToArray();




It uses reflection to set the property which is, by many engineer standards, a serious no-no that will result in a Christmas stocking full of coal. My production version of the above code actually uses dynamically-generated delegates using expression trees to set entity properties (I may post that code for review at another time), but this should get you started. So long as you're not using reflection haphazardly within thousands of iterations, it isn't really that bad, especially these days with faster hardware and the accumulation of all the .NET framework optimizations that have taken place since .NET's early days.



So here's how you use the class:



var BobJones = PersonRepo.GetPersonById(100);
var Tracker = new EntityChangeTracker<Person>(BobJones);

Tracker.Set(e => e.LastName, "Jones");
Tracker.Set(e => e.DateOfBirth, new DateTime(1970, 2, 15));


In that example, you load Bob from the database and make a correction to his last name and DOB. The tracking class will track that only those properties have changed. When you go to generate your update, you just do this:



 var Properties = Tracker.GetChangedProperties();

string Sql = $@"
update persontable
set string.Join(", ", Properties.Select(pi => $"pi.Name = :pi.Name").ToArray())
where id = 100";


My framework knows how to get the entity table name and primary key for the where clause, but this shows how the update fields are generated:



update persontable 
set LastName = :LastName, DateOfBirth = :DateOfBirth
where id = 100


You can then parameterize it like this:



 var Parameters = Properties.Select(p => new YourDbParameter(p.Name, p.GetValue(BobJones)));


So about that love/hate relationship I mentioned earlier. Here are the pros/cons to this:



Pros



  • The automation/encapsulation aspect prevents the need to write massive amounts of boilerplate code within your class, especially when you're dealing with a large number of properties. Going from auto-properties to properties with concrete setters and getters that contain tracking logic can increase your class code by as much as 11 lines of code per property.

  • The extraction of the property name from an expression eliminates magic strings, though .NET 4.6.1 now offers the nameof keyword which can mitigate this as shown in my first example.

  • This solution can be retrofitted for use with any existing class without having to convert every auto-property to complex properties with tracking logic.

Cons:



  • In an effort to eliminate boilerplate code within your class, you end up writing a bit more code anyway in the form of a lambda expressions every time you want to track changes to your class, but this is typically only noticeable with VB.NET and its verbose lambda syntax. If you just bite down and write all the tracking code within your class, you can, as Ron Popeil would say, set it and forget it and only have to update the code whenever you need to add a new property.

Overall, I really think the pros outweigh the cons, but want to see if anyone else can find a better way to achieve what I've done here or extol the virtues of another implementation.










share|improve this question











$endgroup$











  • $begingroup$
    Did you consider t4 for auto-generating boilerplate code? You can also either wrap entities in a generated wrapper that tracks changes to the properties or simply store a copy of the originally retrieved entity inside your Tracker. But maybe my real question is why you spend time writing your own ORM these days instead of focusing on your business logic.
    $endgroup$
    – Mattias Åslund
    May 11 '16 at 17:45










  • $begingroup$
    @MattiasÅslund Haven't heard of T4, but will look into it. I also don't want to store a copy of the original entity because that means I have to make a database call to get it and I am a minimalist when it comes to accessing resources. I am not really sure I understand the last question.
    $endgroup$
    – oscilatingcretin
    May 11 '16 at 17:52













2












2








2





$begingroup$


There are a number of topics pertaining to entity change tracking. All the ones I've seen involve either 1) notifying when a property has changed or 2) merely determining whether or not an entity is dirty.



My goal is quite different. I wrote a mini-repository framework that generates SQL for inserts, selects, updates, and deletes. Updates are particularly tricky because the framework needs to support partial updates. To do this, you have to know which properties have changed and only generate the update SQL for those specific fields. Otherwise, you run the risk of overwriting existing data with nulls or default values unless you load the original entity from the database prior to the update.



Take this person class as an example:



public class Person

public string FirstName get; set;

public string LastName get; set;

public DateTime DateOfBirth get; set;



Quite a bit of boilerplate code would be required to allow it to track its own property changes. Here's an example (leaving LastName and DateOfBirth alone for brevity):



public class Person

HashSet<string> ChangedProperties =
new HashSet<string>(StringComparer.OrdinalIgnoreCase);

string _FirstName = null;
public string FirstName

get return _FirstName;
set

ChangedProperties.Add(nameof(FirstName));
_FirstName = value;



public string LastName get; set;

public DateTime DateOfBirth get; set;

public string[] GetChangedProperties()

return ChangedProperties.ToArray();




Imagine having to do this for 50 properties or more (some of the classes I work with have 90+ properties).



So I came up with a special tracking class that uses generics and expressions to encapsulate all of that boilerplate property code. Having actually begun to use it in my application, I've developed a bit of a love/hate relationship with it.



Here's the watered-down version of the class:



public class PropertyChangeTracker<TEntity> where TEntity : class

TEntity Entity = null;
HashSet<PropertyInfo> ChangedProperties = new HashSet<PropertyInfo>();

public PropertyChangeTracker(TEntity Entity)

this.Entity = Entity;


public void Set<TValue>(Expression<Func<TEntity, TValue>> Expression, TValue Value)

var Member = (Expression.Body as MemberExpression).Member as PropertyInfo;

ChangedProperties.Add(Member);

Member.SetValue(Entity, Value);


public PropertyInfo[] GetChangedProperties()

return ChangedProperties.ToArray();




It uses reflection to set the property which is, by many engineer standards, a serious no-no that will result in a Christmas stocking full of coal. My production version of the above code actually uses dynamically-generated delegates using expression trees to set entity properties (I may post that code for review at another time), but this should get you started. So long as you're not using reflection haphazardly within thousands of iterations, it isn't really that bad, especially these days with faster hardware and the accumulation of all the .NET framework optimizations that have taken place since .NET's early days.



So here's how you use the class:



var BobJones = PersonRepo.GetPersonById(100);
var Tracker = new EntityChangeTracker<Person>(BobJones);

Tracker.Set(e => e.LastName, "Jones");
Tracker.Set(e => e.DateOfBirth, new DateTime(1970, 2, 15));


In that example, you load Bob from the database and make a correction to his last name and DOB. The tracking class will track that only those properties have changed. When you go to generate your update, you just do this:



 var Properties = Tracker.GetChangedProperties();

string Sql = $@"
update persontable
set string.Join(", ", Properties.Select(pi => $"pi.Name = :pi.Name").ToArray())
where id = 100";


My framework knows how to get the entity table name and primary key for the where clause, but this shows how the update fields are generated:



update persontable 
set LastName = :LastName, DateOfBirth = :DateOfBirth
where id = 100


You can then parameterize it like this:



 var Parameters = Properties.Select(p => new YourDbParameter(p.Name, p.GetValue(BobJones)));


So about that love/hate relationship I mentioned earlier. Here are the pros/cons to this:



Pros



  • The automation/encapsulation aspect prevents the need to write massive amounts of boilerplate code within your class, especially when you're dealing with a large number of properties. Going from auto-properties to properties with concrete setters and getters that contain tracking logic can increase your class code by as much as 11 lines of code per property.

  • The extraction of the property name from an expression eliminates magic strings, though .NET 4.6.1 now offers the nameof keyword which can mitigate this as shown in my first example.

  • This solution can be retrofitted for use with any existing class without having to convert every auto-property to complex properties with tracking logic.

Cons:



  • In an effort to eliminate boilerplate code within your class, you end up writing a bit more code anyway in the form of a lambda expressions every time you want to track changes to your class, but this is typically only noticeable with VB.NET and its verbose lambda syntax. If you just bite down and write all the tracking code within your class, you can, as Ron Popeil would say, set it and forget it and only have to update the code whenever you need to add a new property.

Overall, I really think the pros outweigh the cons, but want to see if anyone else can find a better way to achieve what I've done here or extol the virtues of another implementation.










share|improve this question











$endgroup$




There are a number of topics pertaining to entity change tracking. All the ones I've seen involve either 1) notifying when a property has changed or 2) merely determining whether or not an entity is dirty.



My goal is quite different. I wrote a mini-repository framework that generates SQL for inserts, selects, updates, and deletes. Updates are particularly tricky because the framework needs to support partial updates. To do this, you have to know which properties have changed and only generate the update SQL for those specific fields. Otherwise, you run the risk of overwriting existing data with nulls or default values unless you load the original entity from the database prior to the update.



Take this person class as an example:



public class Person

public string FirstName get; set;

public string LastName get; set;

public DateTime DateOfBirth get; set;



Quite a bit of boilerplate code would be required to allow it to track its own property changes. Here's an example (leaving LastName and DateOfBirth alone for brevity):



public class Person

HashSet<string> ChangedProperties =
new HashSet<string>(StringComparer.OrdinalIgnoreCase);

string _FirstName = null;
public string FirstName

get return _FirstName;
set

ChangedProperties.Add(nameof(FirstName));
_FirstName = value;



public string LastName get; set;

public DateTime DateOfBirth get; set;

public string[] GetChangedProperties()

return ChangedProperties.ToArray();




Imagine having to do this for 50 properties or more (some of the classes I work with have 90+ properties).



So I came up with a special tracking class that uses generics and expressions to encapsulate all of that boilerplate property code. Having actually begun to use it in my application, I've developed a bit of a love/hate relationship with it.



Here's the watered-down version of the class:



public class PropertyChangeTracker<TEntity> where TEntity : class

TEntity Entity = null;
HashSet<PropertyInfo> ChangedProperties = new HashSet<PropertyInfo>();

public PropertyChangeTracker(TEntity Entity)

this.Entity = Entity;


public void Set<TValue>(Expression<Func<TEntity, TValue>> Expression, TValue Value)

var Member = (Expression.Body as MemberExpression).Member as PropertyInfo;

ChangedProperties.Add(Member);

Member.SetValue(Entity, Value);


public PropertyInfo[] GetChangedProperties()

return ChangedProperties.ToArray();




It uses reflection to set the property which is, by many engineer standards, a serious no-no that will result in a Christmas stocking full of coal. My production version of the above code actually uses dynamically-generated delegates using expression trees to set entity properties (I may post that code for review at another time), but this should get you started. So long as you're not using reflection haphazardly within thousands of iterations, it isn't really that bad, especially these days with faster hardware and the accumulation of all the .NET framework optimizations that have taken place since .NET's early days.



So here's how you use the class:



var BobJones = PersonRepo.GetPersonById(100);
var Tracker = new EntityChangeTracker<Person>(BobJones);

Tracker.Set(e => e.LastName, "Jones");
Tracker.Set(e => e.DateOfBirth, new DateTime(1970, 2, 15));


In that example, you load Bob from the database and make a correction to his last name and DOB. The tracking class will track that only those properties have changed. When you go to generate your update, you just do this:



 var Properties = Tracker.GetChangedProperties();

string Sql = $@"
update persontable
set string.Join(", ", Properties.Select(pi => $"pi.Name = :pi.Name").ToArray())
where id = 100";


My framework knows how to get the entity table name and primary key for the where clause, but this shows how the update fields are generated:



update persontable 
set LastName = :LastName, DateOfBirth = :DateOfBirth
where id = 100


You can then parameterize it like this:



 var Parameters = Properties.Select(p => new YourDbParameter(p.Name, p.GetValue(BobJones)));


So about that love/hate relationship I mentioned earlier. Here are the pros/cons to this:



Pros



  • The automation/encapsulation aspect prevents the need to write massive amounts of boilerplate code within your class, especially when you're dealing with a large number of properties. Going from auto-properties to properties with concrete setters and getters that contain tracking logic can increase your class code by as much as 11 lines of code per property.

  • The extraction of the property name from an expression eliminates magic strings, though .NET 4.6.1 now offers the nameof keyword which can mitigate this as shown in my first example.

  • This solution can be retrofitted for use with any existing class without having to convert every auto-property to complex properties with tracking logic.

Cons:



  • In an effort to eliminate boilerplate code within your class, you end up writing a bit more code anyway in the form of a lambda expressions every time you want to track changes to your class, but this is typically only noticeable with VB.NET and its verbose lambda syntax. If you just bite down and write all the tracking code within your class, you can, as Ron Popeil would say, set it and forget it and only have to update the code whenever you need to add a new property.

Overall, I really think the pros outweigh the cons, but want to see if anyone else can find a better way to achieve what I've done here or extol the virtues of another implementation.







c# .net






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 11 '16 at 19:26







oscilatingcretin

















asked May 11 '16 at 17:08









oscilatingcretinoscilatingcretin

13116




13116











  • $begingroup$
    Did you consider t4 for auto-generating boilerplate code? You can also either wrap entities in a generated wrapper that tracks changes to the properties or simply store a copy of the originally retrieved entity inside your Tracker. But maybe my real question is why you spend time writing your own ORM these days instead of focusing on your business logic.
    $endgroup$
    – Mattias Åslund
    May 11 '16 at 17:45










  • $begingroup$
    @MattiasÅslund Haven't heard of T4, but will look into it. I also don't want to store a copy of the original entity because that means I have to make a database call to get it and I am a minimalist when it comes to accessing resources. I am not really sure I understand the last question.
    $endgroup$
    – oscilatingcretin
    May 11 '16 at 17:52
















  • $begingroup$
    Did you consider t4 for auto-generating boilerplate code? You can also either wrap entities in a generated wrapper that tracks changes to the properties or simply store a copy of the originally retrieved entity inside your Tracker. But maybe my real question is why you spend time writing your own ORM these days instead of focusing on your business logic.
    $endgroup$
    – Mattias Åslund
    May 11 '16 at 17:45










  • $begingroup$
    @MattiasÅslund Haven't heard of T4, but will look into it. I also don't want to store a copy of the original entity because that means I have to make a database call to get it and I am a minimalist when it comes to accessing resources. I am not really sure I understand the last question.
    $endgroup$
    – oscilatingcretin
    May 11 '16 at 17:52















$begingroup$
Did you consider t4 for auto-generating boilerplate code? You can also either wrap entities in a generated wrapper that tracks changes to the properties or simply store a copy of the originally retrieved entity inside your Tracker. But maybe my real question is why you spend time writing your own ORM these days instead of focusing on your business logic.
$endgroup$
– Mattias Åslund
May 11 '16 at 17:45




$begingroup$
Did you consider t4 for auto-generating boilerplate code? You can also either wrap entities in a generated wrapper that tracks changes to the properties or simply store a copy of the originally retrieved entity inside your Tracker. But maybe my real question is why you spend time writing your own ORM these days instead of focusing on your business logic.
$endgroup$
– Mattias Åslund
May 11 '16 at 17:45












$begingroup$
@MattiasÅslund Haven't heard of T4, but will look into it. I also don't want to store a copy of the original entity because that means I have to make a database call to get it and I am a minimalist when it comes to accessing resources. I am not really sure I understand the last question.
$endgroup$
– oscilatingcretin
May 11 '16 at 17:52




$begingroup$
@MattiasÅslund Haven't heard of T4, but will look into it. I also don't want to store a copy of the original entity because that means I have to make a database call to get it and I am a minimalist when it comes to accessing resources. I am not really sure I understand the last question.
$endgroup$
– oscilatingcretin
May 11 '16 at 17:52










1 Answer
1






active

oldest

votes


















1












$begingroup$

I suggest you using static AOP something like Fody or Postsharp , you do not need change you entity , just add a Attribute to class, TrackChange.Fody can perfect to solve your problem, https://github.com/jrt324/TrackChange





share








New contributor




guaike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$













    Your Answer





    StackExchange.ifUsing("editor", function ()
    return StackExchange.using("mathjaxEditing", function ()
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    );
    );
    , "mathjax-editing");

    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f128113%2ftracking-which-entity-properties-have-changed%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1












    $begingroup$

    I suggest you using static AOP something like Fody or Postsharp , you do not need change you entity , just add a Attribute to class, TrackChange.Fody can perfect to solve your problem, https://github.com/jrt324/TrackChange





    share








    New contributor




    guaike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.






    $endgroup$

















      1












      $begingroup$

      I suggest you using static AOP something like Fody or Postsharp , you do not need change you entity , just add a Attribute to class, TrackChange.Fody can perfect to solve your problem, https://github.com/jrt324/TrackChange





      share








      New contributor




      guaike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      $endgroup$















        1












        1








        1





        $begingroup$

        I suggest you using static AOP something like Fody or Postsharp , you do not need change you entity , just add a Attribute to class, TrackChange.Fody can perfect to solve your problem, https://github.com/jrt324/TrackChange





        share








        New contributor




        guaike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.






        $endgroup$



        I suggest you using static AOP something like Fody or Postsharp , you do not need change you entity , just add a Attribute to class, TrackChange.Fody can perfect to solve your problem, https://github.com/jrt324/TrackChange






        share








        New contributor




        guaike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.








        share


        share






        New contributor




        guaike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.









        answered 9 mins ago









        guaikeguaike

        1111




        1111




        New contributor




        guaike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.





        New contributor





        guaike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.






        guaike is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Code Review Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f128113%2ftracking-which-entity-properties-have-changed%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            名間水力發電廠 目录 沿革 設施 鄰近設施 註釋 外部連結 导航菜单23°50′10″N 120°42′41″E / 23.83611°N 120.71139°E / 23.83611; 120.7113923°50′10″N 120°42′41″E / 23.83611°N 120.71139°E / 23.83611; 120.71139計畫概要原始内容臺灣第一座BOT 模式開發的水力發電廠-名間水力電廠名間水力發電廠 水利署首件BOT案原始内容《小檔案》名間電廠 首座BOT水力發電廠原始内容名間電廠BOT - 經濟部水利署中區水資源局

            Prove that NP is closed under karp reduction?Space(n) not closed under Karp reductions - what about NTime(n)?Class P is closed under rotation?Prove or disprove that $NL$ is closed under polynomial many-one reductions$mathbfNC_2$ is closed under log-space reductionOn Karp reductionwhen can I know if a class (complexity) is closed under reduction (cook/karp)Check if class $PSPACE$ is closed under polyonomially space reductionIs NPSPACE also closed under polynomial-time reduction and under log-space reduction?Prove PSPACE is closed under complement?Prove PSPACE is closed under union?

            Is my guitar’s action too high? Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern)Strings too stiff on a recently purchased acoustic guitar | Cort AD880CEIs the action of my guitar really high?Μy little finger is too weak to play guitarWith guitar, how long should I give my fingers to strengthen / callous?When playing a fret the guitar sounds mutedPlaying (Barre) chords up the guitar neckI think my guitar strings are wound too tight and I can't play barre chordsF barre chord on an SG guitarHow to find to the right strings of a barre chord by feel?High action on higher fret on my steel acoustic guitar