我有一个更新方法,它接受最后一个活动项并用新值克隆它,并将活动标志设置为true。我的问题是更新方法是由多个web api方法调用的,因此最后一个活动项并不总是相同。我最终得到了多个活动项和数据不一致。所以我想把所有电话联系起来解决这个问题,但我不知道从哪里开始。
[HttpPost]
[Route("Route2")]
[ValidateModel]
public async Task<HttpResponseMessage> Post(string contractReference, [FromBody] Family input)
{
return await CallPartialUpdate(contractReference, p => p.Family = input);
}
[HttpPost]
[Route("Route3")]
[ValidateModel]
public async Task<HttpResponseMessage> Post(string contractReference, [FromBody] Address input)
{
return await CallPartialUpdate(contractReference, p => p.Address = input);
}
private async Task<HttpResponseMessage> CallPartialUpdate(string reference, Item itemToUpdate)
{
try
{
var existingItem = _bContext.RetrieveLastActive(reference);
if (existingItem == null)
return Request.CreateResponse(HttpStatusCode.NotFound);
var newRecord = existingItem.Document.Clone();
newRecord.update(itemToUpdate);
newRecord.active = true;
await _bContext.PutDocumentAsync(newRecord, reference);
return Request.CreateResponse(HttpStatusCode.Created);
}
catch (System.Exception exception)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, exception.Message);
}
}`
基于@Asti的答案,我创建了一个带有Rx observable的单元测试但是我仍然在最后一项中有数据不一致所以我如何得到这个工作以及我如何获得callPartialUpdate()的结果谢谢
[TestFixture]
public class Concurrency
{
[Test]
public async Task Update_Should_Always_Change_Last_Item()
{
var observer = Observable.Timer(TimeSpan.FromMilliseconds(1));
var items = new List<Item>()
{
new Item() { FirstName = "AA", LastName = "BB" , IsActive = true },
new Item() { FirstName = "A", LastName = "A" , IsActive = false },
};
await Task.Run(() =>
{
Parallel.Invoke(async () => await observer.Select(item => Observable.FromAsync(ct => UpdateItem(items, new Item() { FirstName = "AAA" })))
.Concat(),
async () => await observer.Select(item => Observable.FromAsync(ct => UpdateItem(items, new Item() { LastName = "BBB" })))
.Concat());
});
var lastItem = items.Single(w => w.IsActive);
Assert.AreEqual("AAA", lastItem.FirstName);
Assert.AreEqual("BBB", lastItem.LastName);
}
public async Task<bool> UpdateItem(List<Item> items, Item itemToUpdate)
{
return await Task.Run(() => update(items, itemToUpdate));
}
private bool update(List<Item> items, Item itemToUpdate)
{
var lastItem = items.Single(w => w.IsActive == true);
lastItem.IsActive = false;
var newItem = new Item()
{
FirstName = string.IsNullOrEmpty(itemToUpdate.FirstName) ? lastItem.FirstName : itemToUpdate.FirstName,
LastName = string.IsNullOrEmpty(itemToUpdate.LastName) ? lastItem.LastName : itemToUpdate.LastName,
IsActive = true
};
items.Add(newItem);
return true;
}
}
答案 0 :(得分:1)
对于可更新的序列,可枚举或可观察:
updates
.Select(item => Observable.FromAsync(ct => CallPartialUpdate(item)))
.Concat();
如果您想要基于Rx的API,那么
答案 1 :(得分:0)
添加
public class Concurrency
{
private Object thisLock = new Object();
然后
private bool update(List<Item> items, Item itemToUpdate)
{
lock (thisLock)
{
var lastItem = items.Single(w => w.IsActive == true);
lastItem.IsActive = false;
var newItem = new Item()
{
FirstName = string.IsNullOrEmpty(itemToUpdate.FirstName) ? lastItem.FirstName : itemToUpdate.FirstName,
LastName = string.IsNullOrEmpty(itemToUpdate.LastName) ? lastItem.LastName : itemToUpdate.LastName,
IsActive = true
};
items.Add(newItem);
}
return true;
}
锁中的区域在任何给定时间都只能由一个线程运行,并且将按预期运行。
无法保证您必须以不同的方式执行此操作 - 以何种方式取决于您要执行的规则。