Tracking which entity properties have changed The 2019 Stack Overflow Developer Survey Results...
Carnot-Caratheodory metric
Does duplicating a spell with Wish count as casting that spell?
Is it possible for the two major parties in the UK to form a coalition with each other instead of a much smaller party?
Are there any other methods to apply to solving simultaneous equations?
Which Sci-Fi work first showed weapon of galactic-scale mass destruction?
Deadlock Graph and Interpretation, solution to avoid
What could be the right powersource for 15 seconds lifespan disposable giant chainsaw?
What do the Banks children have against barley water?
Access elements in std::string where positon of string is greater than its size
Inversion Puzzle
Is three citations per paragraph excessive for undergraduate research paper?
Why can Shazam do this?
Should I use my personal or workplace e-mail when registering to external websites for work purpose?
"What time...?" or "At what time...?" - what is more grammatically correct?
Is bread bad for ducks?
Inflated grade on resume at previous job, might former employer tell new employer?
Can distinct morphisms between curves induce the same morphism on singular cohomology?
Why could you hear an Amstrad CPC working?
What do hard-Brexiteers want with respect to the Irish border?
What are the motivations for publishing new editions of an existing textbook, beyond new discoveries in a field?
Geography at the pixel level
Is domain driven design an anti-SQL pattern?
How to make payment on the internet without leaving a money trail?
Does it makes sense to buy a new cycle to learn riding?
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;
}
$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.
c# .net
$endgroup$
add a comment |
$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.
c# .net
$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
add a comment |
$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.
c# .net
$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
c# .net
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
add a comment |
$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
add a comment |
1 Answer
1
active
oldest
votes
$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
New contributor
$endgroup$
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
$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
New contributor
$endgroup$
add a comment |
$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
New contributor
$endgroup$
add a comment |
$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
New contributor
$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
New contributor
New contributor
answered 31 mins ago
guaikeguaike
1111
1111
New contributor
New contributor
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
$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