Access Current NHibernate Session in Castle Windsor IOC Container - fluent-nhibernate

I am trying to access my current nhibernate session using IOC from within a running Quartz.net Job and every time it comes back as null stating the following:
'NHibernateSession.Current' threw an exception of type 'SharpArch.Domain.PreconditionException' NHibernate.ISession SharpArch.Domain.PreconditionException}. An ISessionStorage has not been configured
Here is my current code setup. I cannot figure out for the life of me how to setup my IOC so that the NHibernate ISession within my IScheduledMessageQueries query is set correctly. The Quartz triggers are working correctly, I just cannot access the ISession to call my queries from within the Job. Any help and/or advice?
Global.cs Code:
protected virtual void InitializeServiceLocator()
{
_container = new WindsorContainer(new XmlInterpreter()).Install(new WebWindsorInstaller());
StartQuartzScheduler();
ComponentRegistrar.AddComponentsTo(_container);
ServiceLocator.SetLocatorProvider(() => new WindsorServiceLocator(_container));
DependencyResolver.SetResolver(new WindsorDependencyResolver(_container));
var activator = new WebApiControllerFactory(_container);
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), activator);
}
private static void StartQuartzScheduler()
{
ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
IJobFactory jobFactory = new WindsorJobFactory(_container);
var scheduler = schedulerFactory.GetScheduler();
scheduler.JobFactory = jobFactory;
scheduler.Start();
var sendScheduledMessageJob = new JobDetailImpl("sendScheduledMessageJob", typeof(SendScheduledMessageJob));
var trigger = new CalendarIntervalTriggerImpl
{
StartTimeUtc = DateTime.UtcNow.Subtract(new TimeSpan(1)),
Name = "Daily Trigger",
RepeatIntervalUnit = IntervalUnit.Second,
RepeatInterval = 1
};
scheduler.ScheduleJob(sendScheduledMessageJob, trigger);
}
public class SendScheduledMessageJob : IJob
{
private readonly IScheduledMessageQueries _scheduledMessageQueries;
public SendScheduledMessageJob(IScheduledMessageQueries scheduledMessageQueries)
{
_scheduledMessageQueries = scheduledMessageQueries;
}
public void Execute(IJobExecutionContext context)
{
var unsentScheduledMessages =
_scheduledMessageQueries.GetAllUnsentScheduledMessages(DateTime.Now);
}
}

Related

Testing Activity Compensate with MassTransit

I'm trying to test the compensation logic in my Activity, but I can't figure out how to kick off the Compensate method in a test. I have an activity that should throw an exception if something isn't found in the DB. I've figured out how to ensure that the activity in faulted in this case, but I can't figure out the compensation part.
My test class is below. Note that awaiting on the RoutingSlipActivityCompensated handler throws a TaskCanceledException. How do I test the compensation part of the activity?
[TestClass]
public class DisableTeamCheckInsActivityTests
{
Mock<ILogger<DisableTeamCheckInsActivity>> _logger;
CheckInsDbContext _db;
InMemoryTestHarness _harness;
ActivityTestHarness<DisableTeamCheckInsActivity, DisableTeamCheckIns, DisableTeamCheckInsLog> _activity;
[TestInitialize]
public async Task Initialize()
{
_logger = new Mock<ILogger<DisableTeamCheckInsActivity>>();
_db = CheckInDbContextFactory.Create();
_harness = new InMemoryTestHarness
{
TestTimeout = TimeSpan.FromSeconds(5)
};
_activity = _harness.Activity<DisableTeamCheckInsActivity, DisableTeamCheckIns, DisableTeamCheckInsLog>(
_ => new DisableTeamCheckInsActivity(_logger.Object, _db),
_ => new DisableTeamCheckInsActivity(_logger.Object, _db)
);
await _db.Database.EnsureCreatedAsync();
await _harness.Start();
}
[TestCleanup]
public async Task Cleanup()
{
await _db.Database.EnsureDeletedAsync();
await _harness.Stop();
}
[TestMethod]
public async Task Missing_Team_Throws()
{
var teamId = Guid.NewGuid();
var builder = new RoutingSlipBuilder(Guid.NewGuid());
builder.AddSubscription(_harness.BusAddress, RoutingSlipEvents.All);
var faulted = _harness.SubscribeHandler<RoutingSlipActivityFaulted>();
var compensated = _harness.SubscribeHandler<RoutingSlipActivityCompensated>();
builder.AddActivity(_activity.Name, _activity.ExecuteAddress, new
{
TeamId = teamId
});
await _harness.Bus.Execute(builder.Build());
var faultContext = await faulted;
Assert.AreEqual("System.InvalidOperationException", faultContext?.Message?.ExceptionInfo?.ExceptionType);
await compensated; // <-- This throws a TaskCanceledException
}
}
A routing slip with a single activity will never compensate. If the activity faults, the routing slip faults, but there isn't any compensation information in the routing slip because there were not any previous activities.
If the activity completed, and a subsequent activity faulted, then the compensate method would be called, and the ActivityCompensated event would be published.

Why this error comes "The plug-in execution failed because no Sandbox Worker processes are currently available"?

I am using an free trial version of online ms crm 2015 just to understand it and
I wrote this plugin with threads int them
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk; // for Iplugin interface
using nonitcompany; // for earlybinding generated by crmsvcuti.exe
using Microsoft.Crm.Sdk; //for stestate requests
using Microsoft.Crm.Sdk.Messages; //for stestate requests
namespace Plugin_on_create_deact_rec
{
public class account_deactivate:IPlugin
{
public static int semaphore0 = 0, semaphore1 = 0, semaphore2 = 0;
public static IPluginExecutionContext context;
public static IOrganizationServiceFactory factory;
public static IOrganizationService service;
public static IServiceProvider serviceProvider_;
public static Entity accounts;
public static SetStateRequest deactivate;
public static SetStateResponse setstate_response;
public void Execute(IServiceProvider serviceProvider)
{
serviceProvider_ = serviceProvider;
ThreadStart _context = new ThreadStart(context_);
ThreadStart _factory = new ThreadStart(factory_);
ThreadStart _execute = new ThreadStart(execute_);
Thread context_t = new Thread(_context);
Thread factory_t = new Thread(_factory);
Thread execute_t= new Thread(_execute);
context_t.Start();
factory_t.Start();
execute_t.Start();
wait(semaphore0);
}
private static void context_()
{
context = (IPluginExecutionContext)serviceProvider_.GetService(typeof(IPluginExecutionContext));
accounts = (Entity)context.InputParameters["Target"];
EntityReference accounts_reference = new EntityReference();
accounts_reference.LogicalName = accounts.LogicalName;
accounts_reference.Id = accounts.Id;
deactivate = new SetStateRequest();
deactivate.EntityMoniker = accounts_reference;
deactivate.State = new OptionSetValue((int)AccountState.Inactive);
deactivate.Status = new OptionSetValue(2);
signal(semaphore1);
}
private static void factory_()
{
factory = (IOrganizationServiceFactory)serviceProvider_.GetService(typeof(IOrganizationServiceFactory));
service = (IOrganizationService)factory.CreateOrganizationService(context.UserId);
signal(semaphore2);
}
private static void execute_()
{
wait(semaphore1);
wait(semaphore2);
setstate_response = (SetStateResponse)service.Execute(deactivate);
signal(semaphore0);
}
private static void wait(int semaphore)
{
while (semaphore == 0)
{
//do nothing
}
semaphore = semaphore - 1;
}
private static void signal(int semaphore)
{
semaphore = semaphore + 1;
}
}
}
i registerd it on create post syncronous mode in accounts entity .
this error come from then after for every sync plugins registered :
Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: The plug-in execution failed because no Sandbox Worker processes are currently available. Please try again.
System.ServiceModel.CommunicationException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #5CD64A38Detail:
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
<ErrorCode>-2147204723</ErrorCode>
<ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
<Message>The plug-in execution failed because no Sandbox Worker processes are currently available. Please try again.
System.ServiceModel.CommunicationException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #5CD64A38</Message>
<Timestamp>2015-03-12T13:19:42.5150181Z</Timestamp>
<InnerFault i:nil="true" />
<TraceText>
[PluginProfiler.Plugins: PluginProfiler.Plugins.ProfilerPlugin]
[dc99cb02-b6c8-e411-80eb-c4346bada6b4: Plugin_on_create_deact_rec.account_deactivate: Create of account (Profiler)]
</TraceText>
</OrganizationServiceFault>
can any one tell me what the hell happened to my instance of crm ..

NHibernate 3.2: SchemaExport not working with SQLite

I'm using an in-memory db for some quick unit tests, using the following code:
public class MemoryDb
{
private static Configuration configuration;
private static ISessionFactory sessionFactory;
static MemoryDb()
{
configuration = new NHibernate.Cfg.Configuration();
configuration.DataBaseIntegration(x =>
{
x.Driver<SQLite20Driver>();
x.Dialect<SQLiteDialect>();
x.ConnectionProvider<DriverConnectionProvider>();
x.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
x.IsolationLevel = IsolationLevel.ReadCommitted;
x.ConnectionString = "Data Source=:memory:;";
x.Timeout = 255;
x.BatchSize = 100;
x.LogFormattedSql = true;
x.LogSqlInConsole = true;
x.AutoCommentSql = false;
});
configuration.AddMapping(DbHelper.GetAutoMappings());
sessionFactory = configuration.BuildSessionFactory();
}
public static ISession GetSession()
{
var session = sessionFactory.OpenSession();
new SchemaExport(configuration).Execute(true, true, false, session.Connection, null);
return session;
}
}
The problem is that the schema export doesn't seem to be working. On of my tests looks like this:
[Fact]
public void ShouldFindDuplicateByEmail()
{
using (var session = MemoryDb.GetSession())
{
var repo = new NHibernateCustomerRepository(session);
var customer = new Customer();
customer.EmailAddress = "test#test.com";
repo.Save(customer);
var duplicates = repo.FindDuplicates(customer);
Assert.Equal(1, duplicates.Length);
}
}
The test fails with the error no such table: Customers. This all worked with Fluent NHibernate and NHibernate 3.1. I know it's not an issue with the mappings themselves, because the actual application works when I run it against an existing SQL Server db. It only fails when running the tests. Any thoughts?
Edit: If I change only the connection string such that it writes to a file (i.e. x.ConnectionString = "data source=" + Path.GetTempFileName();, the whole thing works. I'm guessing either the schema isn't run correctly against the in-memory db, or it's getting a new in-memory db each time I execute a session command, but have no clue how to figure this out.
I found the answer here: https://forum.hibernate.org/viewtopic.php?p=2397541#p2397541
I had to add the following to the db configuration:
x.ConnectionReleaseMode = ConnectionReleaseMode.OnClose;
Otherwise, NHibernate releases the connection after each statement is flushed, thereby getting rid of the in-memory database with the schema.

Sharepoint 2010 Web Part Communication - How to make consumer wait for the provider

I have a series of web parts I need to implement in SharePoint 2010. The data provider web part uses an UpdatePanel and asynchronously makes a web service call which can potentially be slow. To keep it simple, I've put a single consumer web part on the page (Chart) which will use the consumer as its data provider.
My problem is that I can't get the consumer to wait for the provider - I get a variety of errors but all basically come back to "There is no data available". This may be because it is a Chart web part but the question also applies to the other custom parts I will be developing as they will pull the same data.
The question is: how do I either push data to my consumers when my provider is ready or somehow let them wait for my provider to have data (via polling or whatever).
Note: this is just a prototype, I haven't added error handling, etc yet.
Code is below:
[ToolboxItem(true)]
public partial class ClarityProjectGeneral : System.Web.UI.WebControls.WebParts.WebPart , IWebPartTable
{
public DataTable ProjectVitals = new DataTable(); For web part communication
// bunch of properties
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
InitializeControl();
// For web part communication
// Initialize our datatable so the chart doesn't barf
DataColumn col = new DataColumn();
col.DataType = typeof(string);
col.ColumnName = "Name";
this.ProjectVitals.Columns.Add(col);
col = new DataColumn();
col.DataType = typeof(DateTime);
col.ColumnName = "Start";
this.ProjectVitals.Columns.Add(col);
col = new DataColumn();
col.DataType = typeof(DateTime);
col.ColumnName = "End";
this.ProjectVitals.Columns.Add(col);
}
protected void Page_Load(object sender, EventArgs e)
{
loading.Visible = true;
content.Visible = false;
}
public ClarityObjectClasses.Projects GetProject(string projectID)
{
Clarity.ClarityAbstractorProject ca = new Clarity.ClarityAbstractorProject(this.Username, this.Password);
Dictionary<string, string> queryParams = new Dictionary<string, string>();
queryParams.Add("projectID", projectID);
// Class for making web service call
ClarityObjectClasses.Projects response = new ClarityObjectClasses.Projects();
response = ca.GetProject(queryParams);
return response;
}
protected void Timer1_Tick(object sender, EventArgs e)
{
if (this.ProjectID == null || this.Username == null || this.Password == null)
{
lblConfigError.Visible = true;
lblConfigError.Text = "One or more required configuration values are not set. Please check the web part configuration.";
panelProjectDetails.Visible = false;
}
else
{
loading.Visible = true;
content.Visible = false;
panelProjectDetails.Visible = true;
ClarityObjectClasses.Projects projects = GetProject(this.ProjectID);
//Assign a bunch of values
// For web part communication
LoadTable(projects.Project[0]);
Timer1.Enabled = false;
loading.Visible = false;
content.Visible = true;
}
}
/* Interface functions for Graph Chart communication */
For web part communication
protected void LoadTable(ClarityObjectClasses.Project project)
{
DataRow row = ProjectVitals.NewRow();
row["Name"] = project.name;
row["Start"] = project.start;
row["End"] = project.finish;
this.ProjectVitals.Rows.Add(row);
}
public PropertyDescriptorCollection Schema
{
get
{
return TypeDescriptor.GetProperties(ProjectVitals.DefaultView[0]);
}
}
public void GetTableData(TableCallback callback)
{
callback(ProjectVitals.Rows);
}
public bool ConnectionPointEnabled
{
get
{
object o = ViewState["ConnectionPointEnabled"];
return (o != null) ? (bool)o : true;
}
set
{
ViewState["ConnectionPointEnabled"] = value;
}
}
[ConnectionProvider("Table", typeof(TableProviderConnectionPoint), AllowsMultipleConnections = true)]
public IWebPartTable GetConnectionInterface()
{
return this;
}
public class TableProviderConnectionPoint : ProviderConnectionPoint
{
public TableProviderConnectionPoint(MethodInfo callbackMethod, Type interfaceType, Type controlType, string name, string id, bool allowsMultipleConnections)
: base(callbackMethod, interfaceType, controlType, name, id, allowsMultipleConnections)
{
}
public override bool GetEnabled(Control control)
{
return ((ClarityProjectGeneral)control).ConnectionPointEnabled;
}
}
}
Do not quite understand, but if it helps
You may not use "connectable" web-parts inside UpdatePanel,
because of lack of corresponding events to bind data on asynchronous callback.
I just stumbled across this. I had exactly the same problem trying to implement a custom webpart just as a proof to myself. I applied filters to both my webpart and a list, and then let a chart consume them. What I found was that my webpart sent the wrong data, but the list webpart worked as expected.
So I reflected the XsltListViewWebPart (or whatever it's exact name is) and I discovered that there is an IConnectionData interface. This allows you to specify the dependencies and get the correct delay binding you need. GetRequiresData indicates that there are still more connections to be consumed before the data can be requested.

NHibernate transaction: Why does this result in committed data?

The following code demonstrates a misleading situation in which data
is committed to the database, even though commit is never called on a
transaction.
Could anyone explain why?
[TestFixture]
public class TestFixture
{
[Test]
public void Test()
{
var config = DoConfiguration();
using(var factory = config.BuildSessionFactory())
{
using (var session = factory.OpenSession())
{
CallSessionContext.Bind(session);
using(new TransactionScope())
{
using (session.BeginTransaction())
{
var myEntity = session
.CreateQuery("from myEntity")
.List<MyEntity>()[0];
myEntity.Name = "test name";
}
var myEntity2 = session
.CreateQuery("from myEntity")
.List<MyEntity>()[0];
myEntity2.Name = "test name";
session.Flush();
}
CallSessionContext.Unbind(factory);
}
}
}
}
Explicitly calling session.flush() is persisting your changes. Discussed in detail in this post