Accessing Original Values After Changes
This article is relevant to entity models that utilize the deprecated Visual Studio integration of Telerik Data Access. The current documentation of the Data Access framework is available here.
Telerik Data Access allows you to get the original property values for a tracked domain model entity. The original values are usually the entity's property values as they were before any changes. The original property values could be obtained by using the generic OpenAccessContext.GetOriginalValue<T> method. The method accepts two parameters. The first one is the object that holds the property or field of interest. The second parameter is a string containing the name of the property for which you want to retrieve the original value. Once you call the SaveChanges method, the original property value will be replaced with the one that you have already committed to the database.
The following example illustrates how to use the GetOriginalValue method to retrieve the original value of the Price and Make properties.
using (EntitiesModel dbContext = new EntitiesModel())
{
Car car = dbContext.Cars.FirstOrDefault();
// Make some changes.
car.Make = "NewMake";
car.Model = "NewModel";
car.Rating = 2;
string originalMakeValue = dbContext.GetOriginalValue<string>(car, "Make");
decimal originalRatingValue = dbContext.GetOriginalValue<decimal>(car, "Rating");
}
Using dbContext As New EntitiesModel()
Dim _car As Car = dbContext.Cars.FirstOrDefault()
' Make some changes.
_car.Make = "NewMake"
_car.Model = "NewModel"
_car.Rating = 2
Dim originalMakeValue As String = dbContext.GetOriginalValue(Of String)(_car, "Make")
Dim originalRatingValue As Decimal = dbContext.GetOriginalValue(Of Decimal)(_car, "Rating")
End Using
If the property name you are passing to the GetOriginalValue method is not found, a new InvalidOperationException will be thrown.
The GetOriginalValue method works on reference properties and collections as well. However, in the case of a reference property, there is one significant detail. In order to get the original value, you need to have an actual change to the reference itself, not a change of a property in the referenced object. The following example demonstrates the correct usage of the GetOriginalValue method in the case of a reference property.
using (EntitiesModel dbContext = new EntitiesModel())
{
Car car = dbContext.Cars.FirstOrDefault();
car.Category = dbContext.Categories.LastOrDefault();
Category originalCarCategory = dbContext.GetOriginalValue<Category>(car, "Category");
}
Using dbContext As New EntitiesModel()
Dim _car As Car = dbContext.Cars.FirstOrDefault()
_car.Category = dbContext.Categories.LastOrDefault()
Dim originalCarCategory As Category = dbContext.GetOriginalValue(Of Category)(_car, "Category")
End Using
By default, the GetOriginalValue method will work only in the cases when you are using the changed concurrency control. The GetOriginalValue method will not work out of the box when you have either Version or None concurrency control. In these cases you will have to set the MaintainOriginalValues property to true. This property is accessible through the OpenAccessContextOptions object that is exposed by the OpenAccessContext.
using (EntitiesModel dbContext = new EntitiesModel())
{
dbContext.ContextOptions.MaintainOriginalValues = true;
}
Using dbContext As New EntitiesModel()
dbContext.ContextOptions.MaintainOriginalValues = True
End Using
This will allow Telerik Data Access always to retrieve the old values of your properties before settings new ones. Note that this might be a performance issue for your application as an additional query will be generated for obtaining the original value of the property you are about to change. If you attempt to invoke the GetOriginalValue method on an object when the concurrency control is not set to changed and the MaintainOriginalValues property is not set to true, then a new NotSupportedException will be thrown.
When you are using the changed concurrency control, you don't have to set the MaintainOriginalValues property to true. The changed concurrency control is working by storing the original values, so they will be available without this option.