Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
EF6:SaveChanges覆盖,已更改的实体未在WPF中更新_Wpf_Entity Framework - Fatal编程技术网

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

EF6:SaveChanges覆盖,已更改的实体未在WPF中更新,wpf,entity-framework,Wpf,Entity Framework,我在EF6 DbContext中有一个覆盖的SaveChanges,在这里我设置了一些日期和用户。这些更改正在保存到数据库中,但我必须退出并重新打开WPF表单,然后才能在那里看到它们 SaveChanges覆盖是: //make sure we get all the changed objects ChangeTracker.DetectChanges(); ObjectContext ctx = ((IObjectContextAdapter) this).ObjectContext;

我在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);
}    
privateReliskContext上下文//我们的模型上下文(通过服务)
私有DataServiceCollection actionStatusBinding//我们合订的藏品
私有集合viewSource viewSource//集合的视图源
私有委托无效操作ResultCallback()//分派器调用的委托
公共管理状态()
{
初始化组件();
}
已加载私有无效页面(对象发送方,路由目标e)
{
//获取CollectionViewSource对象
viewSource=((CollectionViewSource)(this.FindResource(“actionStatusesViewSource”));
尝试
{
UIHelper.ProgressBarRun(真);
//初始化上下文
context=new RegRiskContext(新Uri(RegRiskSettings.Default.ServiceURL));
//创建一个为异步操作准备好的查询
DataServiceQuery dsq=context.actionStatus;
尝试
{
dsq.BeginExecute(OnQueryCompleted,dsq);
}
捕获(DataServiceClientException ex)
{
Show(例如ToString());
}
/*同步版本
*注意打开车窗时的冻结
var q=context.ActionStatuses.OrderBy(f=>f.Id);
DataServiceCollection ActionStatus=新的DataServiceCollection(q);
viewSource.Source=操作状态;
*/
}
捕获(例外情况除外)
{
MessageBox.Show(例如Message);
}
}
私有void OnQueryCompleted(IAsyncResult结果)
{
//从状态缓存中获取原始查询对象。
DataServiceQuery=(DataServiceQuery)result.AsyncState;
//使用Dispatcher确保我们在UI线程上!
this.Dispatcher.BeginInvoke(新操作结果调用(委托
{
尝试
{
//使用查询结果实例化绑定集合
actionStatusBinding=newDataServiceCollection(query.EndExecute(result));
//将源设置为集合
viewSource.Source=actionStatusBinding;
UIHelper.ProgressBarRun(假);
}
捕获(DataServiceRequestException ex)
{
Show(例如ToString());
}
}),空);
}
私有无效保存按钮\u单击(对象发送方,路由目标)
{
尝试
{
UIHelper.ProgressBarRun(真);
context.BeginSaveChanges(OnSaveChangesCompleted,null);
}
捕获(DataServiceClientException ex)
{
Show(例如ToString());
}
}
保存更改上的私有无效已完成(IAsyncResult结果)
{
//使用Dispatcher确保操作在UI线程中返回。
this.Dispatcher.BeginInvoke(新操作结果调用(委托
{
尝试
{
//完成保存更改操作。
EndSaveChanges(结果);
viewSource.View.Refresh();
UIHelper.ProgressBarRun(假);
}
捕获(DataServiceRequestException ex)
{
Show(例如ToString());
}
}),空);
}    
我不知道这是否是因为我的SaveChanges覆盖需要以某种方式通知?或者如果WPF是错误的?
WPF和EF之间有一个WCF DataServices层,但这看起来很“简单”,我甚至看不出我可以在那里做些什么更改。

找到了一个解决方案,但不完全确定为什么要修复它,因此任何扩展的解释都将受到感激

我的WCF数据服务类很简单:

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
    }
}
公共类RegRiskService:EntityFrameworkDataService
{
//此方法只调用一次以初始化服务范围策略。
公共静态void InitializeService(DataServiceConfiguration配置)
{
//TODO:设置规则以指示哪些实体集和服务操作是可见的、可更新的等。
config.DataServiceBehavior.MaxProtocolVersion=DataServiceProtocolVersion.V3;
//剪断访问内容
}
}
这是协议版本,默认为v2,将其更改为v3似乎解决了问题。我的WPF datagrid现在使用SaveChanges覆盖中所做的更改进行更新

同样,对于任何有相同原始问题的人都有一个警告,我已经研究这个问题有一段时间了,所以有可能我改变了其他一些东西,这才是真正的根本原因