EF6:SaveChanges覆盖,更改了WPF中未更新的实体

时间:2014-09-08 14:31:49

标签: wpf entity-framework

我在EF6 DbContext中有一个重写的SaveChanges,我在其中设置了一些日期和用户。这些更改正在保存到数据库中,但我必须退出并重新打开我的WPF表单,然后才能在那里看到。

SaveChanges覆盖是:

//make sure we get all the changed objects
ChangeTracker.DetectChanges();

ObjectContext ctx = ((IObjectContextAdapter) this).ObjectContext;

//get the current user name...
//TODO needs checking that this works when via service.
string userID = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
userID = userID.Substring(userID.IndexOf('\\') + 1);    //remove domain

foreach (var dbEntityEntry in ctx.ObjectStateManager
    .GetObjectStateEntries(EntityState.Added | EntityState.Modified)
    .Where(e => e.Entity is IAuditInfo))
{

    switch (dbEntityEntry.State)
    {
        case EntityState.Added:
            ((IAuditInfo) dbEntityEntry.Entity).CreatedOn = DateTime.Now;
            ((IAuditInfo) dbEntityEntry.Entity).CreatedBy = userID;
            break;
        case EntityState.Modified:
            ((IAuditInfo) dbEntityEntry.Entity).LastUpdatedOn = DateTime.Now;
            ((IAuditInfo) dbEntityEntry.Entity).LastUpdatedBy = userID;
            break;
        case EntityState.Deleted:
        case EntityState.Detached:
        case EntityState.Unchanged:
        default:
            break;
    }

}

ctx.SaveChanges(SaveOptions.None);

return base.SaveChanges();

我的WPF XAML:

<Page.Resources>
    <CollectionViewSource x:Key="actionStatusesViewSource"
                          d:DesignSource="{d:DesignInstance my:ActionStatus, CreateList=True}" />

</Page.Resources>

<Grid DataContext="{StaticResource actionStatusesViewSource}"
      Margin="5">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition />
    </Grid.RowDefinitions>

    <DataGrid Grid.Row ="1" 
              AutoGenerateColumns="False"
              EnableRowVirtualization="True"
              ItemsSource="{Binding}"
              Name="actionStatusesDataGrid"
              RowDetailsVisibilityMode="VisibleWhenSelected"
              VerticalAlignment="Top"
              ClipboardCopyMode="IncludeHeader">
        <DataGrid.Columns>
            <DataGridTextColumn x:Name="idColumn"
                                Binding="{Binding Path=Id, Mode=TwoWay}"
                                Header="Id"
                                Width="SizeToHeader" />
            <DataGridTextColumn x:Name="nameColumn"
                                Binding="{Binding Path=Name, Mode=TwoWay}"
                                Header="Name"
                                Width="256" />
            <DataGridTemplateColumn x:Name="validFromColumn"
                                    Header="Valid From"
                                    Width="128">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <DatePicker SelectedDate="{Binding Path=ValidFrom, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn x:Name="validToColumn"
                                    Header="Valid To"
                                    Width="128">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <DatePicker SelectedDate="{Binding Path=ValidTo, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn x:Name="lastUpdatedByColumn"
                                Binding="{Binding Path=LastUpdatedBy, Mode=TwoWay}"
                                Header="Updated By"
                                Width="SizeToHeader" />
            <DataGridTextColumn x:Name="lastUpdatedOnColumn"
                                Binding="{Binding Path=LastUpdatedOn, Mode=TwoWay, StringFormat=\{0:dd/MM/yyyy HH:mm\}}"
                                Header="Updated On"
                                Width="SizeToCells" />
            <DataGridTextColumn x:Name="createdByColumn"
                                Binding="{Binding Path=CreatedBy, Mode=TwoWay}"
                                Header="Created By"
                                Width="SizeToHeader" />
            <DataGridTextColumn x:Name="createdOnColumn"
                                Binding="{Binding Path=CreatedOn, Mode=TwoWay, StringFormat=\{0:dd/MM/yyyy HH:mm\}}"
                                Header="Created On"
                                Width="SizeToCells" />
        </DataGrid.Columns>
    </DataGrid>  

最后我加载并保存代码:

private RegRiskContext context;             //our model context (via the service)
private DataServiceCollection<ActionStatus> actionStatusBinding;  //our bound collection
private CollectionViewSource viewSource;    //the view source for the collection

private delegate void OperationResultCallback(); //delegate for the dispatcher invokes

public AdminActionStatus()
{
    InitializeComponent();
}

private void Page_Loaded(object sender, RoutedEventArgs e)
{
    //get the CollectionViewSource object
    viewSource = ((CollectionViewSource) (this.FindResource("actionStatusesViewSource")));

    try
    {
        UIHelper.ProgressBarRun(true);

        //initialise the context
        context = new RegRiskContext(new Uri(RegRiskSettings.Default.ServiceURL));

        //create a query ready for the async operation
        DataServiceQuery<ActionStatus> dsq = context.ActionStatuses;

        try
        {
            dsq.BeginExecute(OnQueryCompleted, dsq);
        }
        catch (DataServiceClientException ex)
        {
            MessageBox.Show(ex.ToString());
        }

        /* synchronous version
         * note the freeze when opening the window
        var q = context.ActionStatuses.OrderBy(f => f.Id);

        DataServiceCollection<ActionStatus> actionStatuses = new DataServiceCollection<ActionStatus>(q);

        viewSource.Source = actionStatuses;
        */
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

private void OnQueryCompleted(IAsyncResult result)
{
    // Get the original query object from the state cache.
    DataServiceQuery<ActionStatus> query = (DataServiceQuery<ActionStatus>) result.AsyncState;

    //use Dispatcher to ensure we're on the UI thread!
    this.Dispatcher.BeginInvoke(new OperationResultCallback(delegate
        {
            try
            {
                //instantiate the binding collection using results of the query
                actionStatusBinding = new DataServiceCollection<ActionStatus>(query.EndExecute(result));

                //set the Source to the collection
                viewSource.Source = actionStatusBinding;

                UIHelper.ProgressBarRun(false);
            }
            catch (DataServiceRequestException ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }), null);
}

private void saveButton_Click(object sender, RoutedEventArgs e)
{
    try
    {
        UIHelper.ProgressBarRun(true);
        context.BeginSaveChanges(OnSaveChangesCompleted, null);
    }
    catch (DataServiceClientException ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

private void OnSaveChangesCompleted(IAsyncResult result)
{
    // Use the Dispatcher to ensure that the operation returns in the UI thread. 
    this.Dispatcher.BeginInvoke(new OperationResultCallback(delegate
        {
            try
            {
                // Complete the save changes operation.
                context.EndSaveChanges(result);

                viewSource.View.Refresh();

                UIHelper.ProgressBarRun(false);
            }
            catch (DataServiceRequestException ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }), null);
}    

我不知道是否因为我的SaveChanges覆盖需要以某种方式通知?或者如果它的WPF错了? 在WPF和EF之间有一个WCF DataServices层,但看起来很简单&#39;够了,我无法看到我甚至可以改变它。

1 个答案:

答案 0 :(得分:0)

找到了一个解决方案,但并不完全确定为什么它会修复它,所以任何扩展的解释都会感激不尽。

我的WCF DataService类很简单:

public class RegRiskService : EntityFrameworkDataService<BOI.RegRisk.Model.RegRiskContext>
{
    // This method is called only once to initialize service-wide policies.
    public static void InitializeService(DataServiceConfiguration config)
    {
        // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
        //snip access stuff
    }
}

这是协议版本,默认为v2,将其更改为v3似乎已经解决了问题。我的WPF数据网格现在使用SaveChanges覆盖中所做的更改进行了更新。

对于任何有同样原始问题的人来说,还有一个警告,我一直在看这个问题,所以有可能我改变了其他的东西,这是真正的根本原因!