问题
I am novice in EF. So to test the optimistic concurrency I used EF 5,WPF and an already created database.The WPF project contains a MainWindow
Having TextBox1
for searching customer via primary key,TextBox2
for customer's name edit,a textblock (txtLog)
to log Field values and a save button. To simulate Concurrency access, in SQL Server 2008
Management Studio i excute the query
"update client set r01_nomcli = 'GGGGG' where r01_codcli = '4112010002';
"
before clicking on save Button. it works fine and DbUpdateConcurrencyException
is fired, but The original values of the entity were lost and take the same values
as those of the current values. This is because of the "using" block which causes the detachment of the entities. To solve this problem, i have to declare the context just before the constructor of the window and instantiate it in "Window_Loaded
" event
Is There another to make this ???
Helps about best practice of Using EF and how Building reusable DAL with EF 5 will be welcome.
Thanks.
Below the code :
public partial class OptimisticConcurrency : Window
{
//client is an entity
client _currentClient = null;
public OptimisticConcurrency()
{
InitializeComponent();
}
//**************************TextBox1 PreviewKeyDown Event Handler
private void TextBox_PreviewKeyDown_1(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
using (dbleaseEntities context = new dbleaseEntities())
{
_currentClient = context.client.Find(txtCode.Text);
if (_currentClient == null)
MessageBox.Show("Customer " + txtCode.Text + " not found.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
else
this.DataContext = _currentClient;
}
}
}
//*****************Save Button Click Event Handler
private void Button_Click_2(object sender, RoutedEventArgs e)
{
using (dbleaseEntities context = new dbleaseEntities())
{
context.Configuration.ValidateOnSaveEnabled = false;
try
{
context.Entry(_currentClient).State = System.Data.EntityState.Modified;
context.SaveChanges();
MessageBox.Show("Success.", "Save", MessageBoxButton.OK, MessageBoxImage.Information);
}
catch (DbEntityValidationException ex)
{
string ss = "";
foreach (var error in ex.EntityValidationErrors)
ss = string.Join(Environment.NewLine, error.ValidationErrors.Select(v => v.ErrorMessage));
MessageBox.Show(ss, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
catch (DbUpdateConcurrencyException ex)
{
string StrValues= "";
DbPropertyValues ov = ex.Entries.Single().OriginalValues;
DbPropertyValues cv = ex.Entries.Single().CurrentValues;
DbPropertyValues dv = ex.Entries.Single().GetDatabaseValues();
StrValues= "Original value : " + ov["r01_nomcli"] + Environment.NewLine +
"Current value : " + cv["r01_nomcli"] + Environment.NewLine +
"Database value : " + dv["r01_nomcli"];
txtLog.Text = StrValues
}
}
}
回答1:
You have roughly three options
- Do what you're doing now - i.e. keep the object connected to context
- Use self tracking entities: http://blogs.msdn.com/b/efdesign/archive/2009/03/24/self-tracking-entities-in-the-entity-framework.aspx
- Use GetDatabaseValues
来源:https://stackoverflow.com/questions/14871294/ef-5-originalvalues-are-lost-when-context-is-disposed