我创建了一个WCF服务,其配置为InstanceMode = PerCall和ConcurrencyMode = Multiple。
但是我在与其中一个实例方法的同步中遇到了问题。有时不会使用正确的Class属性值调用它。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class InvestorService : IInvestorService
public void ProcessPartnerChunk(short PartnerChunkTypeId, int JobID, int? PartnerID, string serializedChunk, string ClientName)
{
PartnerChunkProcessor pcp = new PartnerChunkProcessor(JobID, PartnerID, serializedChunk, ClientName);
switch ((PartnerChunkType)PartnerChunkTypeId)
{
case PartnerChunkType.ChunkTypeX:
pcp.ProcessChunkStageX();
break;
case PartnerChunkType.ChunkTypeY:
pcp.ProcessChunkStageY();
break;
default: break;
}
PartnerChunkProcessor如下所示: -
public class PartnerChunkProcessor
{
private static object _syncLocker = new object();
#region "Properties"
public int? PartnerID { get; set; }
public int K1JobId { get; set; }
public string SerializedChunk { get; set; }
public string Client { get; set; }
#endregion
#region "Constructors"
private PartnerChunkProcessor() { }
public PartnerChunkProcessor(int K1JobID, int? PID, string Chunk, string ClientName)
{
K1JobId = K1JobID;
PartnerID = PID;
SerializedChunk = Chunk;
Client = ClientName;
}
#endregion
public void ProcessChunkStageX() //IDMS_PartnerTradeGroups
{
DataModelEntities dmxContext = new DataModelEntities();
//[Step-1]
//Deserialize the incoming XML data into the original business obj.
List<IDMS_PartnerTradeGroups> chunkPTG = SerializerManager.Deserialize<List<IDMS_PartnerTradeGroups>>(SerializedChunk);
//[Step-2]
////Dummy manipulation of the dataset (Business Logic evaluation).
List<IDMS_PartnerTradeGroups> lstTarget = new List<IDMS_PartnerTradeGroups>();
foreach (IDMS_PartnerTradeGroups ptx in chunkPTG)
{
lstTarget.Add(ptx);
}
////Add a record with the total value of NumberOfUnits for the partner.
if (lstTarget.Count > 0)
{
decimal? totalUnits = lstTarget.Sum(sx => sx.NumberOfUnits);
lstTarget.Add(new IDMS_PartnerTradeGroups
{
PartnerID = Convert.ToInt32(PartnerID),
CalendarMonth = 12,
CalendarYear = DateTime.Now.Year,
NumberOfUnits = totalUnits,
PartnerGroupID = "0",
TransactionMonth = 1,
TransactionYear = DateTime.Now.Year
});
}
//[Step-3]
////Serialize the calculated object into the XML and save it in DB.
if (lstTarget.Count > 0)
{
string targetSerializedXML = SerializerManager.Serialize<List<IDMS_PartnerTradeGroups>>(lstTarget);
dmxContext.uspSave_IDMS_PartnerTradeGroups_Data(PartnerID, targetSerializedXML, false);
//[Step-4] Save the Serialized output into REDIS server.
PersistToRedis(targetSerializedXML, "IDMS_PartnerTradeGroups", MethodBase.GetCurrentMethod().Name, PartnerID, Client);
//[Step-5]
//Update the Chunk-Call-Stack status
lock (_syncLocker)
{
UpdateChunkCall((int)Constants.PartnerChunkType.ChunkTypeX, K1JobId, PartnerID);
}
}
}
private void UpdateChunkCall(int partnerChunkTypeId, int k1JobId, int? partnerId)
{
ChunkCallStack currChunkStack = new ChunkCallStack();
DataModelEntities dmContext = new DataModelEntities();
currChunkStack = dmContext.ChunkCallStacks.Where(wx => wx.K1JobId == k1JobId
&& wx.PartnerId == partnerId
&& wx.ReadyToRetire == false
&& wx.PartnerChunkTypeId == partnerChunkTypeId)
.FirstOrDefault<ChunkCallStack>();
if (currChunkStack != null)
{
currChunkStack.ChunkStatus = 20; ////Completed
currChunkStack.Message = "Processing Complete";
currChunkStack.DateUpdated = DateTime.UtcNow;
currChunkStack.UpdatedBy = "Investor-Service";
dmContext.Entry(currChunkStack).State = System.Data.Entity.EntityState.Modified;
dmContext.SaveChanges();
}
}
public void ProcessChunkStageY() //IDMS_PartnerTradeGroupTimeLine
{
//[Step-1]
List<IDMS_PartnerTradeGroupTimeLine> chunkPTG = SerializerManager.Deserialize<List<IDMS_PartnerTradeGroupTimeLine>>(SerializedChunk);
//[Step-2]
////Dummy manipulation of the dataset (Business Logic evaluation).
List<IDMS_PartnerTradeGroupTimeLine> lstTarget = new List<IDMS_PartnerTradeGroupTimeLine>();
foreach (IDMS_PartnerTradeGroupTimeLine ptx in chunkPTG)
{
lstTarget.Add(ptx);
}
////Add a record with the total value of NumberOfUnits for the partner.
if (lstTarget.Count > 0)
{
decimal totalUnits = lstTarget.Sum(sx => sx.NumberOfUnits);
lstTarget.Add(new IDMS_PartnerTradeGroupTimeLine
{
PartnerID = Convert.ToInt32(PartnerID),
CalcMonth = 12,
CalcYear = DateTime.Now.Year,
NumberOfUnits = totalUnits,
TradeGroup = "Total",
TradeMonth = 12,
TradeYear = DateTime.Now.Year
});
}
//[Step-3]
////Serialize the calculated object into the XML and save it in DB.
if (lstTarget.Count > 0)
{
string targetSerializedXML = SerializerManager.Serialize<List<IDMS_PartnerTradeGroupTimeLine>>(lstTarget);
DataModelEntities dmxContext = new DataModelEntities();
dmxContext.uspSave_IDMS_PartnerTradeGroupsTimeline_Data(PartnerID, targetSerializedXML, false);
//[Step-5]
//Update the Chunk-Call-Stack status
lock (_syncLocker)
{
UpdateChunkCall((int)Constants.PartnerChunkType.ChunkTypeY, K1JobId, PartnerID);
}
}
}
}
[第5步] 给了我很多麻烦。我甚至添加了锁(_locker)块来包含ORM调用,但仍然没有运气。由于并发模式=多次,有时数据不会保存到数据库中。这个问题是随机发生的,很难将其解决。
但是当我翻转并发模式Mode = Single时,它就像一个魅力。
我想知道,我应该添加哪些更改以使其适用于多并发模式。 PartnerChunkProcessor是一个具有所需属性集的简单类,我认为它在这里发生了同步问题。
请告知。