public void CreateUser(UserCreationSpec userToCreate) { if (userToCreate == null) { throw new ArgumentNullException(nameof(userToCreate)); } userToCreate.Validate(); /* * Typical usage of SessionScope for a read-write business transaction. * It's as simple as it looks. */ using (var sessionScope = _sessionScopeFactory.Create()) { //-- Build domain model var user = new User() { Id = userToCreate.Id, Name = userToCreate.Name, Email = userToCreate.Email, WelcomeEmailSent = false, CreatedOn = DateTime.UtcNow }; //-- Persist _userRepository.Add(user); sessionScope.SaveChanges(); } }
public void UpdateCreditScoreForAllUsers() { /* * Demo of SessionScope + parallel programming. */ using (var sessionScope = _sessionScopeFactory.Create()) { //-- Get all users var session = sessionScope.Session; var userIds = session.CreateCriteria <User>().List <User>().Select(u => u.Id).ToList(); Console.WriteLine("Found {0} users in the database. Will calculate and store their credit scores in parallel.", userIds.Count); //-- Calculate and store the credit score of each user // We're going to imagine that calculating a credit score of a user takes some time. // So we'll do it in parallel. // You MUST call SuppressAmbientScope() when kicking off a parallel execution flow // within a SessionScope. Otherwise, this SessionScope will remain the ambient scope // in the parallel flows of execution, potentially leading to multiple threads // accessing the same ISession instance. using (_sessionScopeFactory.SuppressAmbientScope()) { Parallel.ForEach(userIds, UpdateCreditScore); } // Note: SaveChanges() isn't going to do anything in this instance since all the changes // were actually made and saved in separate DbScopes created in separate threads. sessionScope.SaveChanges(); } }
public void Intercept(IInvocation invocation) { var sessionScopeAttribute = invocation.MethodInvocationTarget .GetCustomAttributes(typeof(SessionScopeAttribute), true) .FirstOrDefault() as SessionScopeAttribute; if (sessionScopeAttribute != null) { var returnType = invocation.MethodInvocationTarget.ReturnType; if (returnType == typeof(Task) || returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task <>)) { var ctArgument = invocation.Arguments.FirstOrDefault(a => a is CancellationToken); var cancellationToken = (CancellationToken?)ctArgument ?? CancellationToken.None; var scope = _scopeFactory .Create(sessionScopeAttribute.ReadOnly, sessionScopeAttribute.Option, sessionScopeAttribute.IsolationLevel); invocation.Proceed(); invocation.ReturnValue = InterceptAsync((dynamic)invocation.ReturnValue, scope, cancellationToken); } else { using (var scope = _scopeFactory .Create(sessionScopeAttribute.ReadOnly, sessionScopeAttribute.Option, sessionScopeAttribute.IsolationLevel)) { invocation.Proceed(); scope.SaveChanges(); } } } else { invocation.Proceed(); } }