Fluently.Configure throws "Database was not configured through Database method" exception - fluent-nhibernate

I am trying to get an in-house application up and running for debugging and when I start the solution, it fails calling the Fluently.Configure() method. Digging into the exception, I see the potential reason as "Database was not configured through Database method."
public static ISessionFactory IdCardSessionFactoryWeb
{
get
{
if (_idCardSessionFactoryWeb != null) return _idCardSessionFactoryWeb;
var cfg = new Configuration();
cfg.DataBaseIntegration(x =>
{
x.ConnectionString = ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString;
x.Driver<SybaseAdoNet4Driver>();
x.Dialect<SybaseAdoNet4Dialect>();
x.Batcher<SybaseASEBatcherFactory>();
});
_idCardSessionFactoryWeb = Fluently.Configure(cfg)
.ExposeConfiguration(c => c
.SetInterceptor(new ABCInterceptor())
.SetProperty(Environment.ShowSql, "true")
.SetProperty(Environment.WrapResultSets, "true")
.SetProperty("command_timeout", timeout)
.SetProperty("current_session_context_class", "web"))
.Mappings(m =>
m.FluentMappings.AddFromAssemblyOf<Batch>())
.BuildSessionFactory();
return _idCardSessionFactoryWeb;
}
}

Looks like I needed to update the nuget package, and then restart my solution.

Related

Programmatic configuration of NLog in ASP.NET Core application to filter unwanted chatter?

I'm attempting to filter out all the unnecessary chatter from the Microsoft hosting assemblies, while still allowing Debug-level messages from our own code to pass through to our logging targets.
Here's code that configures NLog and initializes a web app. Unfortunately, the Microsoft.* and System.* namespace filtering does not functional at all. The result is that all messages Debug and higher are logged.
I do not want to use the old nlog.config process. I want to be able to build the LoggingConfiguration in code.
I really must be missing something easy here, but I don't see it!
public static void Main(string[] args)
{
// Read configuration from a variety of sources to compose our final IConfiguration
var config = ReadOurConfigFromLotsOfPlaces();
var nLogConfig = new LoggingConfiguration();
var consoleTarget = new ColoredConsoleTarget("console")
{
AutoFlush = true,
ErrorStream = true,
Layout = #"${date:format=yyyy-MM-dd HH\:mm\:ss.fff} ${level} [${logger}] - ${message}${onexception:${newline}}${exception:format=shortType,message,stackTrace:maxInnerExceptionLevel=5}"
};
nLogConfig.AddTarget(consoleTarget);
nLogConfig.LoggingRules.Add(new LoggingRule("Microsoft.*", LogLevel.Warn, consoleTarget) {Final = true});
nLogConfig.LoggingRules.Add(new LoggingRule("System.*", LogLevel.Warn, consoleTarget) {Final = true});
nLogConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, consoleTarget));
var logger = NLogBuilder.ConfigureNLog(nLogConfig).GetCurrentClassLogger();
logger.Debug("NLog initialization complete");
try
{
logger.Debug("init main");
CreateHostBuilder(config).Build().Run();
}
catch (Exception exception)
{
logger.Error(exception, "Stopped program because of exception");
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
LogManager.Shutdown();
}
}
public static IWebHostBuilder CreateHostBuilder(IConfiguration config)
{
// we don't call CreateDefaultBuilder() because we already have assembled the configuration we want to use
return new WebHostBuilder()
.UseConfiguration(config)
.UseKestrel(options => options.UseSystemd())
.UseStartup<Startup>()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
})
.UseNLog();
}
Any tips would be greatly appreciated.
Ugh. I understand my problem now: The 'LoggingRules' is looking for a positive match between logger name and the min/max level values, so my first two LoggingRule objects did not match messages coming from the Microsoft.* and System.* namespaces, so the rules did nothing with those messages.
In order to accomplish the filtering I want, this is the solution:
var nLogConfig = new LoggingConfiguration();
var consoleTarget = new ColoredConsoleTarget("console")
{
AutoFlush = true,
ErrorStream = true,
Layout = #"${date:format=yyyy-MM-dd HH\:mm\:ss.fff} ${level} [${logger}] - ${message}${onexception:${newline}}${exception:format=shortType,message,stackTrace:maxInnerExceptionLevel=5}"
};
nLogConfig.AddTarget(consoleTarget);
var nullTarget = new NullTarget("null");
nLogConfig.AddTarget(nullTarget);
// matches every Microsoft.* logger with a LogLevel less than LogLevel.Warn
nLogConfig.LoggingRules.Add(new LoggingRule("Microsoft.*", LogLevel.Trace, LogLevel.Info, nullTarget) {Final = true});
// matches every System.* logger with a LogLevel less than LogLevel.Warn
nLogConfig.LoggingRules.Add(new LoggingRule("System.*", LogLevel.Trace, LogLevel.Info, nullTarget) {Final = true});
// and everything else, LogLevel.Debug and higher
nLogConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, consoleTarget));

Why am I getting this error from NLog during integration testing: LayoutRenderer cannot be found

I added some aspnet layout renderers to my NLog configuration, and everything works fine for my website, but when I try to run my integration tests, they fail with this error message:
NLog.NLogConfigurationException : Error when setting property 'Layout' on NLog.Targets.DatabaseParameterInfo
----> System.ArgumentException : LayoutRenderer cannot be found: 'aspnet-request-cookie'. Is NLog.Web not included?
My initial instinct was to follow their suggestion and add the NLog.Web.AspNetCore package to my integration Test project. That did not do anything.
Here's what my integration test setup looks like:
[OneTimeSetUp]
public static void BaseOneTimeSetUp()
{
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Development";
Assume.That(environment, Is.AnyOf("Development", "CI"), "Integration tests can only run in one of those environments");
var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<IHostingEnvironment>(p =>
{
var mock = new Mock<IHostingEnvironment>();
mock.SetupGet(m => m.ContentRootPath).Returns(TestContext.CurrentContext.TestDirectory);
mock.SetupGet(m => m.EnvironmentName).Returns(environment);
return mock.Object;
});
Startup.AddConfiguration(serviceCollection); //throws NLogConfigurationException
}
And here's my implementation for the Startup AddConfiguration method:
public static void AddConfiguration(IServiceCollection services)
{
services.AddSingleton<IConfiguration>(s =>
{
var env = s.GetService<IHostingEnvironment>();
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", false, true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
var config = builder.Build();
// This next line throws the NLogConfigurationException
LogManager.Configuration = new NLogLoggingConfiguration(config.GetSection("NLog"));
return config;
});
}
The integration test is not calling the UseNLog method for the asp.net WebHost, as shown in their example code:
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
})
.UseNLog(); // NLog: setup NLog for Dependency injection
If you don't want to set up a WebHost for your tests, you can make do with a Mock<IWebHostBuilder>.
All you need to do is add this to your test setup before configuring NLog:
var mockHostBuilder = new Mock<IWebHostBuilder>();
mockHostBuilder.Object.UseNLog();

QueryInterceptor not firing

I created a QueryInterceptor on a dataservice in WCF (within SharePoint).
The "InitializeService" method is called and I'm able to debug that one,
but my QueryInterceptors don't get fired.
[QueryInterceptor("Requests")]
public Expression<Func<Request, bool>> FilterRequests()
{
Debugger.Break();
if (SPContext.Current == null) throw new DataServiceException(401, "Permission Denied");
var spUser = SPContext.Current.Web.CurrentUser;
var spLoginName = spUser.LoginName;
var spGroups = spUser.Groups.Cast<SPGroup>().Select(x => x.Name);
if (spGroups.Any(x => x == _HRApproversGroupName))
return (u) => true;
throw new DataServiceException(401, "Permission Denied");
}
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("Users", EntitySetRights.AllRead);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
config.UseVerboseErrors = true;
}
Anyone who knows what I'm doing wrong or haven't done yet?
The problem was that I referenced to the wrong QueryInterceptor (I referenced to another assembly, but with same namespaces)

NHibernate Validator not integrating with Fluent NHibernate

I'm having some trouble getting NHV to work with Fluent NHibernate. A unit test that I have that has an entity that SHOULD be failing validation ends up throwing an ADO exception. I have NHV configured the following way:
private static void Init()
{
_SessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(connectionString)
.ShowSql())
.Mappings(m =>
m.FluentMappings.AddFromAssemblyOf<SessionFactory>()
.ExportTo(pathToExportMappingsTo))
.ProxyFactoryFactory("NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu")
.ExposeConfiguration(ConfigureNhibernateValidator)
.BuildSessionFactory();
}
private static void ConfigureNhibernateValidator(Configuration config)
{
var nhvConfiguration = new NHibernate.Validator.Cfg.Loquacious.FluentConfiguration();
nhvConfiguration
.SetDefaultValidatorMode(ValidatorMode.OverrideAttributeWithExternal)
.Register(Assembly.Load("Business.Objects")
.ValidationDefinitions())
.IntegrateWithNHibernate
.RegisteringListeners();
ValidatorEngine validatorEngine = new ValidatorEngine();
validatorEngine.Configure(nhvConfiguration);
ValidatorInitializer.Initialize(config, validatorEngine);
}
I've looked over this configuration several times now and scoured the internet to try and find out what's wrong with this. I've also looked at examples provided in the NHV source but I haven't been able to figure out why my unit test does not throw an InvalidStateException. I have a unit test to validate the same entity that should be failing that validates it directly via the validation engine and this works.
Does anyone see anything wrong with the above configuration?
I'm using NHibernate 3.1, NHibernate Validator 1.3 and Fluent NHibernate 1.2.0.712
I debugged this and it seemed that when it went to validate my entity it was initialize my validator engine again. I corrected this by changing the ConfigureNhibernateValidator(Configuration config) method above to the following (the key here was to set the SharedEngineProvider):
private static void ConfigureNhibernateValidator(Configuration config)
{
var provider = new NHibernateSharedEngineProvider();
NHibernate.Validator.Cfg.Environment.SharedEngineProvider = provider;
var nhvConfiguration = new NHibernate.Validator.Cfg.Loquacious.FluentConfiguration();
nhvConfiguration
.SetDefaultValidatorMode(ValidatorMode.OverrideAttributeWithExternal)
.Register(Assembly.Load("Business.Objects")
.ValidationDefinitions())
.IntegrateWithNHibernate
.AvoidingDDLConstraints()
.RegisteringListeners();
ValidatorEngine validatorEngine = NHibernate.Validator.Cfg.Environment.SharedEngineProvider.GetEngine();
validatorEngine.Configure(nhvConfiguration);
ValidatorInitializer.Initialize(config, validatorEngine);
}

Why is am I getting a duplicate class mapping error

in my nhibernate session helper class, I load my entities into the configuration like:
static NHibernateHelper()
{
try
{
Configuration cfg = new Configuration();
cfg.Configure();
cfg.AddAssembly(typeof (Category).Assembly);
cfg.AddAssembly(typeof (Product).Assembly);
SessionFactory = cfg.Configure().BuildSessionFactory();
}
catch (Exception ex)
{
}
}
It works fine if I only have 1 cfg.AddAssembly, but loading both Category and Product results in an error?
Are they both in a same assembly (Category and Product). If they are, then you just need one AddAssembly.
i think you are calling Configure twice try removing the first cfg.Configure();
this is how it should look :
static NHibernateHelper(){
try{
Configuration cfg = new Configuration();
cfg.AddAssembly(typeof (Category).Assembly);
cfg.AddAssembly(typeof (Product).Assembly);
SessionFactory = cfg.Configure().BuildSessionFactory();
}
catch (Exception ex){
}}