How to configure NHibernate SessionFactory in code - c#

I'm new to NHibernate and I'm trying to configure it based on the book 'Learning NHibernate 4'. However, I'm stuck with how to configure it. I have a class called Connection but when I try to use it, NHibernate tells me it can't find 'HbmMapping'.
class Connection
{
public Connection()
{
var cfg = new Configuration();
cfg.DataBaseIntegration(x =>
{
x.Dialect<PostgreSQLDialect>();
x.Driver<NpgsqlDriver>();
x.ConnectionString = "Server=127.0.0.1; Port=5433; User Id=smartwarehouse; Password=$smart#2018;Database=warehouse;";
x.ConnectionReleaseMode = ConnectionReleaseMode.OnClose;
x.LogSqlInConsole = true;
x.LogFormattedSql = true;
}).AddMapping(GetMappings());
}
// here is Hbm dosn't find from library
private HbmMapping GetMappings()
{
}
}
it gives me other two options to use like here

This is probably a better resource for this issue. You typically tell it where your mappings are at an assembly level...
.AddFromAssemblyOf<YourEntity>();
...so that when you add/remove mappings, you don't need to change your code.
For example, my SessionProvider has a bit like this:
Config = new NHibernateConfig();
Config.Configure(); // read config default style
Fluently
.Configure(Config)
.Mappings(
m => m.FluentMappings.AddFromAssemblyOf<UserMap>()
...
I don't have .hbm files as I use derivatives of ClassMap. However, as long as the type you specify in the AddFromAssemblyOf method is in the same assembly as your .hbm files, then it should work. So something like:
Fluently
.Configure(Config)
.Mappings(
m => m.HbmMappings.AddFromAssemblyOf<ATypeInYourMappingAssembly>()

Related

ASP.NET IConfiguration, how to iterate or enumerate Providers

I am trying to write a test to verify that X providers are loaded in a certain scenario.
I can resolve the IConfiguration object, how can I tell how many IConfigurationProviders are in it?
In my startup, I use totally bog standard Configuration in my Program
IConfiguration configuration = null;
var builder = Host.CreateDefaultBuilder()
.ConfigureServices((hostContext, services) =>
{
configuration = hostContext.Configuration;
var startup = new Startup(hostContext.Configuration, hostContext.HostingEnvironment);
//startup.ConfigureServices(services);
})
.ConfigureAppConfiguration((hostContext, config) =>
{
config.AddAzureKeyVaultsFromConfig();
});
builder.Build();
return configuration;
When I'm debugging, I can see my list of Providers when I hover over configuration.
What I would want to do is see that there are 4 providers. I would also want to check and see what type the providers are.
If I use Enumerate() it just gives me a flattened list of all of the values and discards which provider it came from.
The object you have here is actually an IConfigurationRoot, and that happens to also implement IConfiguration. So if you treat it as such, you can access the Providers property. For example:
IConfigurationRoot configuration = null;
// snip the rest of your code
var providerCount = configuration.Providers.Count();

How to mock IConfiguration.GetValue

I tried in vain to mock a top-level (not part of any section) configuration value (.NET Core's IConfiguration). For example, neither of these will work (using NSubstitute, but it would be the same with Moq or any mock package I believe):
var config = Substitute.For<IConfiguration>();
config.GetValue<string>(Arg.Any<string>()).Returns("TopLevelValue");
config.GetValue<string>("TopLevelKey").Should().Be("TopLevelValue"); // nope
// non generic overload
config.GetValue(typeof(string), Arg.Any<string>()).Returns("TopLevelValue");
config.GetValue(typeof(string), "TopLevelKey").Should().Be("TopLevelValue"); // nope
In my case, I also need to call GetSection from this same config instance.
You can use an actual Configuration instance with in-memory data.
//Arrange
var inMemorySettings = new Dictionary<string, string> {
{"TopLevelKey", "TopLevelValue"},
{"SectionName:SomeKey", "SectionValue"},
//...populate as needed for the test
};
IConfiguration configuration = new ConfigurationBuilder()
.AddInMemoryCollection(inMemorySettings)
.Build();
//...
Now it is a matter of using the configuration as desired to exercise the test
//...
string value = configuration.GetValue<string>("TopLevelKey");
string sectionValue = configuration.GetSection("SectionName").GetValue<string>("SomeKey");
//...
Reference: Memory Configuration Provider
I do not have idea about NSubstitute, but this is how we can do in Moq.
Aproach is same in either cases.
GetValue<T>() internally makes use of GetSection().
You can Mock GetSection and return your Own IConfigurationSection.
This includes two steps.
1). Create a mock for IConfigurationSection (mockSection) & Setup .Value Property to return your desired config value.
2). Mock .GetSection on Mock< IConfiguration >, and return the above mockSection.Object
Mock<IConfigurationSection> mockSection = new Mock<IConfigurationSection>();
mockSection.Setup(x=>x.Value).Returns("ConfigValue");
Mock<IConfiguration> mockConfig = new Mock<IConfiguration>();
mockConfig.Setup(x=>x.GetSection(It.Is<string>(k=>k=="ConfigKey"))).Returns(mockSection.Object);
Mock IConfiguration
Mock<IConfiguration> config = new Mock<IConfiguration>();
SetupGet
config.SetupGet(x => x[It.Is<string>(s => s == "DeviceTelemetryContainer")]).Returns("testConatiner");
config.SetupGet(x => x[It.Is<string>(s => s == "ValidPowerStatus")]).Returns("On");
IConfiguration.GetSection<T> must be mocked indirectly. I don't fully understand why because NSubstitute, if I understand correctly, creates its own implementation of an interface you're mocking on the fly (in memory assembly). But this seems to be the only way it can be done. Including a top-level section along with a regular section.
var config = Substitute.For<IConfiguration>();
var configSection = Substitute.For<IConfigurationSection>();
var configSubSection = Substitute.For<IConfigurationSection>();
configSubSection.Key.Returns("SubsectionKey");
configSubSection.Value.Returns("SubsectionValue");
configSection.GetSection(Arg.Is("SubsectionKey")).Returns(configSubSection);
config.GetSection(Arg.Is("TopLevelSectionName")).Returns(configSection);
var topLevelSection = Substitute.For<IConfigurationSection>();
topLevelSection.Value.Returns("TopLevelValue");
topLevelSection.Key.Returns("TopLevelKey");
config.GetSection(Arg.Is<string>(key => key != "TopLevelSectionName")).Returns(topLevelSection);
// GetValue mocked indirectly.
config.GetValue<string>("TopLevelKey").Should().Be("TopLevelValue");
config.GetSection("TopLevelSectionName").GetSection("SubsectionKey").Value.Should().Be("SubsectionValue");
I could imagine in some rare scenarios it is needed but, in my humble opinion, most of the time, mocking IConfiguration highlight a code design flaw.
You should rely as much as possible to the option pattern to provide a strongly typed access to a part of your configuration. Also it will ease testing and make your code fail during startup if your application is misconfigured (instead than at runtime when the code reading IConfiguration is executed).
If you really(really) need to mock it then I would advice to not mock it but fake it with an in-memory configuration as explained in #Nkosi's answer
While Nkosi's answer works great for simple structures, sometimes you want to be able to have more complex objects (like arrays) without repeating the whole section path and to be able to use the expected types themselves. If you don't really care too much about performance (and should you in your unit tests?) then this extension method might be helpful.
public static void AddObject(this IConfigurationBuilder cb, object model) {
cb.AddJsonStream(new MemoryStream(Encoding.UTF8.GetString(JsonConvert.SerializeObject(model))));
}
And then use it like this
IConfiguration configuration = new ConfigurationBuilder()
.AddObject(new {
SectionName = myObject
})
.Build();
Use SetupGet method to mock the Configuration value and return any string.
var configuration = new Mock<IConfiguration>();
configuration.SetupGet(x => x[It.IsAny<string>()]).Returns("the string you want to return");
We need to mock IConfiguration.GetSection wichs is executed within GetValue extension method.
You inject the IConfiguration:
private readonly Mock<IConfiguration> _configuration;
and the in the //Arrange Section:
_configuration.Setup(c => c.GetSection(It.IsAny())).Returns(new Mock().Object);
It worked like a charm for me.
I've found this solution to work reliably for me for my XUnit C# tests & corresponding C# code:
In Controller
string authConnection = this._config["Keys:AuthApi"] + "/somePathHere/Tokens/jwt";
In XUnit Test
Mock<IConfiguration> mockConfig = new Mock<IConfiguration>();
mockConfig.SetupGet(x => x[It.Is<string>(s => s == "Keys:AuthApi")]).Returns("some path here");

Tables not created using Envers, without errors in compilation

I try create the tables with following code:
protected override void PostProcessMappings(Configuration config)
{
base.PostProcessMappings(config);
var enversConf = new NHibernate.Envers.Configuration.Fluent.FluentConfiguration();
config.Properties.Add("nhibernate.envers.audit_table_prefix", string.Empty); // default
config.Properties.Add("nhibernate.envers.audit_table_suffix", "_REV"); // default _AUD
config.Properties.Add("nhibernate.envers.revision_field_name", "REV"); // default
config.Properties.Add("nhibernate.envers.revision_type_field_name", "REVTYPE"); // default
config.IntegrateWithEnvers(enversConf);
new SchemaExport(config).Create(false, true);
}
But in the schema, i cant see the tables.
I try to implement the code using here (Test). Next, i debug and the nhibernate object: Cfg.NHibernate.Configuration config and in my project i cant catch the mappings, and in the test, i see the mapping that will be created.
I dont know what next i need to do.

When do I pass the RegistrationBuilder to Catalog?

With the new fluent MEF programming model, if I have multiple catalogs:
To which catalog do I pass my RegistrationBuilder to???
Do I need to pass RegistrationBuilder to SatisfyImportsOnce call?
Which of SatisfyImportsOnce or ComposeParts do I use? (has anything changed with this in fluent mef?)
E.g. Here is an example to llustrate my confusion (see comments on the r.h.s):
// Get pre-wired registration builder
RegistrationBuilder rb = new MefCompositionRoot().CommonRegistrationBuilder();
// Register this WCF service class
rb.ForType<LogService>().Export<LogService>();
var assembly = typeof (LogService).Assembly;
var assemblyCatalog = new AssemblyCatalog(assembly, rb); // <-- HERE?
var dirCatalog = new DirectoryCatalog("bin", rb); // <-- and HERE?
// Combine catalogs
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(dirCatalog);
catalog.Catalogs.Add(assemblyCatalog);
var container = new CompositionContainer(catalog);
container.SatisfyImportsOnce(this, rb);// THIS?
container.ComposeParsts(this); ///or THIS?
You can put the RegistrationBuilder to any of the catalogs you want to use MEF Conventions with. If you want to use only the Conventions Model, then use it in all catalogs. If the DirectoryCatalog in your sample code, will load assemblies containing only Attributed exports/imports then you do not need the RegistrationBuilder. Note that both models (Attributed and Contentions) can coexist. So, you could add the RegistrationBuilder to all catalogs unless there might be a type that satisfies a rule (configured using the RegistrationBuilder) that you do not want to use in your CompositionContainer.
This overload of SatisfyImportsOnce is a riddle. From the documentation (and from a quick look at MEF's source) it looks like you can use a specific RegistrationBuilder ad-hoc. In reality I have only managed to use it with the code sample that follows.
SatisfyImportsOnce disables recomposition. Check out this excellent answer on this subject.
Sample using SatisfyImportsOnce(Object, ReflectionContext)
private static void TestLateRegistration_SameBuilder_Ok()
{
var rb = new RegistrationBuilder();
var assemblyCatalog = new AssemblyCatalog(typeof(LogService).Assembly, rb);
using (var container = new CompositionContainer(assemblyCatalog))
{
rb.ForType<LogService>().Export();
var server = new TypeImportingLogService();
//Use the same RegistrationBuilder.
container.SatisfyImportsOnce(server, rb);
}
}

Silverlight waiting for asynchronous call

I have a silverlight application that went it starts up, it needs to read a config file that a webservice returns.
So, in my main page, I want something like this:
public MainPage()
{
InitializeComponent();
Config cfg = new Config();
XDocument config = cfg.getConfig();
//doing stuff with config here
...
}
The constructor for config calls readConfigAsnc and I have a method for the readcompleted that returns the xdocument. I want the readConfigCompleted called before execution continues in MainPage(). What is the best way to go about doing this?
The best way is to separate this out into two methods. Pass a function as a parameter of the getConfig, so like this:
cfg.getConfig( fcnToCall );
Later, in your code,
void fcnToCall( XDocument config )
{
//Do stuff with config here...
}
Another option would be to use lambda expression if you want to retain your local variables:
Config cfg = new Config();
cfg.Callback += new Action<XDocument> action = s =>
{
XDocument cfg = s as XDocument;
//Do stuff with config here...
};
cfg.getConfig();
Why not separate out the methods? Instead of having all of this happen in the MainPage(), have the 'Do Stuff' happen in the GetConfigCompleted event.

Categories

Resources