1

根据这篇文章,我每次调用都使用一个数据上下文,所以在我的 WCF 服务的每个方法中,我使用一个using 块来创建一个新的数据上下文。

但我对以这种方式工作的形式有些怀疑。

例如,我使用存储库中的方法 getAllCLients() 来获取数据库的所有客户端,然后服务向调用该方法的客户端发送包含所有客户端的列表。然后用户修改其中一些的信息,例如三个。修改客户端也许我可以添加到具有修改客户端的列表中。

当我想更新这三个客户端时,我可以调用一个方法 updateClients() 来接收修改后的客户端列表。我如何为每个方法使用一个新的数据上下文,在 updateCients() 中获取一个没有实体的新数据上下文,所以我认为我必须遵循以下步骤:

1.- 创建一个新的数据上下文,其中包含我要更新的客户端。所以我需要为此指定条件。这是一个额外的操作(我之前使用 getAllClients() 方法获取客户端),所以我需要再次获取客户端。

2.- 抛出 DBSet 的客户端集合(我使用 EF 4.1)并更改信息。这让我也去抛出我从客户端应用程序收到的列表。所以我必须去扔两张单子。这需要资源。

3.- 保存更改。无论如何,这都是必需的,因此不需要更多的工作。

有什么方法可以轻松完成第 2 步?在 dataContext 中存在一些方法来将值从我修改的客户端传递到数据上下文中的客户端?我使用 POCO 实体,也许它存在一种简单的方法来做到这一点。

另一个问题是关于并发的。如果我使用允许 EF 的悲观并发来控制并发(例如,带有时间戳字段),最好为每个客户端调用 updateClient() 还是更好地传递所有客户端的列表?我的意思是,如果我使用列表作为参数,如果一个客户端存在并发问题,例如第二个,第一个客户端将正确更新,但第二个不会,第三个也不会。我如何通知用户某些客户端存在问题?

继续,我想知道当我有一个短暂的数据上下文时进行更新的最佳方式。

谢谢。戴姆洛克。

4

1 回答 1

4

该服务是断开连接的场景,因此当您的客户端传回修改后的记录时,您只需将它们处理为已修改。您不需要为此从数据库加载所有记录。

public void SaveClients(List<Client> modifiedClients)
{
    using (var context = new Context())
    {
        modifiedClients.ForEach(c => 
           {
               context.Entry(c).State = EntityState.Modified;
           });
        context.SaveChanges(); 
    }
}

如果您使用的是每次调用服务并且每个服务操作都需要上下文,您可以将上下文实例移动到服务构造函数,因为服务实例将只存在于服务器单个服务调用 = 您不需要using每次调用。如果您这样做,请不要忘记IDisposable在您的服务上实施以处理上下文。

另一个问题是关于并发的。如果我使用允许 EF 的悲观并发控制并发(例如,带有时间戳字段),最好为每个客户端调用 updateClient() 还是更好地传递所有客户端的列表?

EF 不支持开箱即用的悲观并发。使用时间戳是乐观并发,因为它允许其他人使用记录。悲观并发是其他客户端无法选择锁定记录进行更新的应用程序逻辑。

每个记录都解决了并发问题,但这种情况下的问题是事务。每次调用都会SaveChanges导致事务用于处理数据库中的所有更改。因此,如果您修改的任何记录不是最新的,您将获得并发异常并且整个事务被回滚 = 没有记录被更新。

您仍然可以通过将修改记录列表传递给服务来解决该问题(减少客户端和服务之间的往返是最佳实践),但您可以通过调用每条记录来单独处理每条SaveChanges记录。无论如何,这应该非常仔细地考虑,因为每次调用SaveChanges都像单独的工作单元 - 这真的是你想要的吗?

顺便提一句。最好的做法是让你的服务无状态。你应该避免在服务调用之间维护数据,这个例子真的不需要它。

于 2012-04-15T19:23:12.313 回答