/// <summary> /// Find existing instance of ProcessManager /// </summary> /// <typeparam name="T"></typeparam> /// <param name="mapper"></param> /// <param name="message"></param> /// <returns></returns> public IPersistanceData <T> FindData <T>(IProcessManagerPropertyMapper mapper, Message message) where T : class, IProcessManagerData { var mapping = mapper.Mappings.FirstOrDefault(m => m.MessageType == message.GetType()) ?? mapper.Mappings.First(m => m.MessageType == typeof(Message)); var collectionName = typeof(T).Name; IMongoCollection <MongoDbSslData <T> > collection = _mongoDatabase.GetCollection <MongoDbSslData <T> >(collectionName); var indexOptions = new CreateIndexOptions(); var indexKeys = Builders <MongoDbSslData <T> > .IndexKeys.Ascending("Data.CorrelationId"); var indexModel = new CreateIndexModel <MongoDbSslData <T> >(indexKeys, indexOptions); collection.Indexes.CreateOne(indexModel); object msgPropValue = null; try { msgPropValue = mapping.MessageProp.Invoke(message); } catch { return(null); } if (null == msgPropValue) { throw new ArgumentException("Message property expression evaluates to null"); } //Left ParameterExpression pe = Expression.Parameter(typeof(MongoDbSslData <T>), "t"); Expression left = Expression.Property(pe, typeof(MongoDbSslData <T>).GetTypeInfo().GetProperty("Data")); foreach (var prop in mapping.PropertiesHierarchy.Reverse()) { left = Expression.Property(left, left.Type, prop.Key); } //Right Expression right = Expression.Constant(msgPropValue, msgPropValue.GetType()); Expression expression; try { expression = Expression.Equal(left, right); } catch (InvalidOperationException ex) { throw new Exception("Mapped incompatible types of ProcessManager Data and Message properties.", ex); } Expression <Func <MongoDbSslData <T>, bool> > lambda = Expression.Lambda <Func <MongoDbSslData <T>, bool> >(expression, pe); return(collection.AsQueryable().FirstOrDefault(lambda)); }
public MongoDbProcessManagerFinderTests() { _connectionString = "mongodb://localhost/"; _dbName = "ProcessManagerRepository"; var mongoClient = new MongoClient(_connectionString); MongoServer server = mongoClient.GetServer(); MongoDatabase mongoDatabase = server.GetDatabase(_dbName); _collection = mongoDatabase.GetCollection<TestData>("TestData"); _collection.Drop(); _mapper = new ProcessManagerPropertyMapper(); _mapper.ConfigureMapping<IProcessManagerData, Message>(m => m.CorrelationId, pm => pm.CorrelationId); }
public MongoDbSslProcessManagerFinderTests() { _dbName = "ScTestProcessManagerRepository"; _connectionString = string.Format("nodes={0},username={1},password={2},cert={3}", "xxx", "xxx", "xxx", "xxx"); _mapper = new ProcessManagerPropertyMapper(); _mapper.ConfigureMapping <IProcessManagerData, Message>(m => m.CorrelationId, pm => pm.CorrelationId); var testRepo = new MongoDbSslRepository(_connectionString, _dbName); testRepo.MongoDatabase.DropCollection("TestDataSsl"); }
public SqlServerProcessManagerFinderTest() { _connectionString = @"Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\MyLocalDb.mdf;Integrated Security=True"; // DROP TABLE before each test using (var connection = new SqlConnection(_connectionString)) { connection.Open(); using (var command = new SqlCommand()) { command.Connection = connection; command.CommandText = "IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'TestSqlServerData') " + "DROP TABLE TestSqlServerData;"; command.ExecuteNonQuery(); } } _mapper = new ProcessManagerPropertyMapper(); _mapper.ConfigureMapping<IProcessManagerData, Message>(m => m.CorrelationId, pm => pm.CorrelationId); }
public SqlServerProcessManagerFinderTest() { var appBasePath = PlatformServices.Default.Application.ApplicationBasePath; //_connectionString = @"Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\MyLocalDb.mdf;Integrated Security=True"; _connectionString = string.Format(@"Data Source=(LocalDB)\v11.0;AttachDbFilename={0};Integrated Security=True", Path.Combine(appBasePath, "MyLocalDb.mdf")); // DROP TABLE before each test using (var connection = new SqlConnection(_connectionString)) { connection.Open(); using (var command = new SqlCommand()) { command.Connection = connection; command.CommandText = "IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'TestSqlServerData') " + "DROP TABLE TestSqlServerData;"; command.ExecuteNonQuery(); } } _mapper = new ProcessManagerPropertyMapper(); _mapper.ConfigureMapping <IProcessManagerData, Message>(m => m.CorrelationId, pm => pm.CorrelationId); }
protected virtual void ConfigureHowToFindProcessManager(IProcessManagerPropertyMapper mapper) { }
public IPersistanceData <T> FindData <T>(IProcessManagerPropertyMapper mapper, Message message) where T : class, IProcessManagerData { return(Finder.FindData <T>(mapper, message)); }
public IPersistanceData <T> FindData <T>(IProcessManagerPropertyMapper mapper, Message message) where T : class, IProcessManagerData { throw new NotImplementedException(); }
/// <summary> /// Find existing instance of ProcessManager /// FindData() and UpdateData() are part of the same transaction. /// FindData() opens new connection and transaction. /// UPDLOCK is placed onf the relevant row to prevent reads until the transaction is commited in UpdateData /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public IPersistanceData <T> FindData <T>(IProcessManagerPropertyMapper mapper, Message message) where T : class, IProcessManagerData { var mapping = mapper.Mappings.FirstOrDefault(m => m.MessageType == message.GetType()) ?? mapper.Mappings.First(m => m.MessageType == typeof(Message)); string tableName = typeof(T).Name; var sbXPath = new StringBuilder(); sbXPath.Append("(/" + tableName); foreach (var prop in mapping.PropertiesHierarchy.Reverse()) { sbXPath.Append("/" + prop.Key); } sbXPath.Append(")[1]"); XPathExpression xPathExpression; try { xPathExpression = XPathExpression.Compile(sbXPath.ToString()); } catch (XPathException ex) { Logger.ErrorFormat("Error compiling xpath expression. {0}", ex.Message); throw; } // Message Propery Value object msgPropValue = mapping.MessageProp.Invoke(message); SqlServerData <T> result = null; if (!GetTableNameExists(tableName)) { return(null); } using (var sqlConnection = new SqlConnection(_connectionString)) { sqlConnection.Open(); using (var command = new SqlCommand()) { command.Connection = sqlConnection; command.CommandTimeout = _commandTimeout; command.CommandText = string.Format(@"SELECT * FROM {0} WHERE DataXml.value('{1}', 'nvarchar(max)') = @val", tableName, xPathExpression.Expression); command.Parameters.Add(new SqlParameter { ParameterName = "@val", Value = msgPropValue }); try { var reader = command.ExecuteReader(CommandBehavior.SingleResult); if (reader.HasRows) { reader.Read(); var serializer = new XmlSerializer(typeof(T)); object res; using (TextReader r = new StringReader(reader["DataXml"].ToString())) { res = serializer.Deserialize(r); } result = new SqlServerData <T> { Id = (Guid)reader["Id"], Data = (T)res, Version = (int)reader["Version"] }; } reader.Dispose(); } finally { sqlConnection.Close(); } } } return(result); }
public IPersistanceData <T> FindData <T>(IProcessManagerPropertyMapper mapper, Message message) where T : class, IProcessManagerData { lock (_memoryCacheLock) { var mapping = mapper.Mappings.FirstOrDefault(m => m.MessageType == message.GetType()) ?? mapper.Mappings.First(m => m.MessageType == typeof(Message)); object msgPropValue = null; try { msgPropValue = mapping.MessageProp.Invoke(message); } catch { return(null); } if (null == msgPropValue) { throw new ArgumentException("Message property expression evaluates to null"); } //Left ParameterExpression pe = Expression.Parameter(typeof(MemoryData <T>), "t"); Expression left = Expression.Property(pe, typeof(MemoryData <T>).GetTypeInfo().GetProperty("Data")); foreach (var prop in mapping.PropertiesHierarchy.Reverse()) { left = Expression.Property(left, left.Type, prop.Key); } //Right Expression right = Expression.Constant(msgPropValue, msgPropValue.GetType()); Expression expression; try { expression = Expression.Equal(left, right); } catch (InvalidOperationException ex) { throw new Exception("Mapped incompatible types of ProcessManager Data and Message properties.", ex); } Expression <Func <MemoryData <T>, bool> > lambda = Expression.Lambda <Func <MemoryData <T>, bool> >(expression, pe); // get all the relevant cache items //var cacheItems = (from n in Cache.AsParallel() where n.Value.GetType() == typeof(MemoryData<IProcessManagerData>) select n.Value); IList <object> cacheItems = new List <object>(); foreach (var key in _provider.Keys()) { var value = _provider.Get <string, object>(key.ToString()); if (value.GetType() == typeof(MemoryData <IProcessManagerData>)) { cacheItems.Add(value); } } // convert to correct generic type //var newCacheItems = Enumerable.ToList((from dynamic cacheItem in cacheItems select new MemoryData<T> { Data = cacheItem.Data, Version = cacheItem.Version })); var newCacheItems = Enumerable.ToList((from dynamic cacheItem in cacheItems select new MemoryData <T> { Data = cacheItem.Data, Version = cacheItem.Version })); // filter based of mapping criteria MemoryData <T> retval = newCacheItems.FirstOrDefault(lambda.Compile()); return(retval); } }
/// <summary> /// Find existing instance of ProcessManager /// </summary> /// <typeparam name="T"></typeparam> /// <param name="mapper"></param> /// <param name="message"></param> /// <returns></returns> public IPersistanceData <T> FindData <T>(IProcessManagerPropertyMapper mapper, Message message) where T : class, IProcessManagerData { if (message is StartProcessManagerMessage) { return(null); } var mapping = mapper.Mappings.FirstOrDefault(m => m.MessageType == message.GetType()) ?? mapper.Mappings.First(m => m.MessageType == typeof(Message)); var collectionName = typeof(T).Name; MongoCollection <T> collection = _mongoDatabase.GetCollection <T>(collectionName); object msgPropValue = mapping.MessageProp.Invoke(message); if (null == msgPropValue) { throw new ArgumentException("Message property expression evaluates to null"); } //Left ParameterExpression pe = Expression.Parameter(typeof(MyMongoData <T>), "t"); Expression left = Expression.Property(pe, typeof(MyMongoData <T>).GetTypeInfo().GetProperty("Data")); foreach (var prop in mapping.PropertiesHierarchy.Reverse()) { left = Expression.Property(left, left.Type, prop.Key); } //Right Expression right = Expression.Constant(msgPropValue, msgPropValue.GetType()); Expression expression; try { expression = Expression.Equal(left, right); } catch (InvalidOperationException ex) { throw new Exception("Mapped incompatible types of ProcessManager Data and Message properties.", ex); } var lambda = Expression.Lambda <Func <MyMongoData <T>, bool> >(expression, pe); IMongoQuery query = Query <MyMongoData <T> > .Where(lambda); // check if data is locked FindAndModifyResult result = collection.FindAndModify(new FindAndModifyArgs { Query = Query.And( Query.Or( Query.EQ("Locked", false), Query.LTE("LockTimeout", DateTime.UtcNow) ), query ), Update = Update.Combine( Update.Set("Locked", true), Update.Set("LockTimeout", DateTime.UtcNow.AddSeconds(30)) ) }); if (result.ModifiedDocument == null) { // spin until lock is released while (true) { result = collection.FindAndModify(new FindAndModifyArgs { Query = Query.And( Query.Or( Query.EQ("Locked", false), Query.LTE("LockTimeout", DateTime.UtcNow) ), query ), Update = Update.Combine( Update.Set("Locked", true), Update.Set("LockTimeout", DateTime.UtcNow.AddSeconds(30)) ) }); // Found unlocked data if (result.ModifiedDocument != null) { break; } Thread.Sleep(100); } } return(result.GetModifiedDocumentAs <MyMongoData <T> >()); }
public InMemoryProcessManagerFinderTests() { _mapper = new ProcessManagerPropertyMapper(); _mapper.ConfigureMapping<IProcessManagerData, Message>(m => m.CorrelationId, pm => pm.CorrelationId); }
public InMemoryProcessManagerFinderTests() { _mapper = new ProcessManagerPropertyMapper(); _mapper.ConfigureMapping <IProcessManagerData, Message>(m => m.CorrelationId, pm => pm.CorrelationId); }