Fluent nHibernate - can't set the batch size - c#

I try to enable the Bach Size in my SessionFactory:
Fluently.Configure()
.Database(MySQLConfiguration.Standard.AdoNetBatchSize(1)
.ConnectionString("xxx"))
.Mappings(m => m.FluentMappings.AddFromAssembly(...))
.ExposeConfiguration(c => c.SetProperty("adonet.batch_size", "1"))
.BuildSessionFactory();
but when I want to set the value of the batch size:
Session = _sessionFactory.OpenSession();
Session.SetBatchSize(25);
Session.FlushMode = FlushMode.Commit;
I still get that error:
No batch size was defined for the session factory, batching is
disabled. Set adonet.batch_size = 1 to enable batching.

You should use
MySqlClientBatchingBatcherFactory
Thus, something like
Fluently.Configure()
.Database(MySQLConfiguration.Standard
.ConnectionString("xxx"))
.Mappings(m => m.FluentMappings.AddFromAssembly(...))
.ExposeConfiguration(c => c.DataBaseIntegration(prop =>
{
prop.BatchSize = 50;
prop.Batcher<MySqlClientBatchingBatcherFactory>();
}))
.BuildSessionFactory();
should work.
Please see these answers: Fluent NHibernate MySQL batching or MySQL NHibernate Batcher if you had further problems with batching; they show other ways to implement it.
Take into account that NHibernate prior to ¿4.0? did not support (natively) batching when combined with MySQL, and a external package was needed (due to some mysql dependencies). After this version, however, the batcher was included into the main trunk so these answers are still valid.
If you use NHibernate 4+, no problems should arise.

Related

EFCore 2.2.6 vs 5.0.8 noTracking

We have an application which was originally running on EFCore 2.2.6 and .Net Core 2.1. We have the below code to query and delete data, it uses AsNoTracking:
var deletedDiag = _unitOfWork.GetRepository<DIAGNOSIS_DETAIL>()
.GetAll(c => c.Diag.CMS_CASE_ID == model.DiagnosisModel.CASE_ID)
.Include(i => i.Diag).AsNoTracking().ToList();
if (deletedDiag != null)
{
foreach (var del in deletedDiag)
{
if (!model.SUBDETAILS.Any(a => a.DIAGNOSIS_DETAIL_ID == del.DIAGNOSIS_DETAIL_ID))
{
_unitOfWork.GetRepository<DIAGNOSIS_DETAIL>().Delete(del);
}
}
}
And Delete does:
public void Delete(TEntity entity) => _dbSet.Remove(entity);
The deletedDiag query has a include to bring in Diag as a navigational property, above this block of code another query gets the same Diag and marks it for update.
In EFCore 2.2.6 the delete works fine, it's able to update the Diag and then run the delete even though the deletedDiag has a path to it, there are no errors. In EFCore 5.0.8, we get an error stating that the entity is already being tracked when we try to delete, the fix was to get the deletedDiag to stop tracking it but setting it to null:
deletedDiag.ForEach(x => x.Diag = null);
that works, but why does it work in 2.2.6?
This is due to the capricious path EF-core has taken right from the start in lots of features and defaults. It was impossible to keep track of all changes between versions, even though they were fairly well documented.
One of those changes in v3 onward was in the area of no-tracking behavior. In EF-core 2, AsNoTracking performed identity resolution, which ensures that all occurrences of an entity with a given key in the result set are represented by the same entity instance. In EF-core 3 this was abandoned: each occurrence of the "same" entity now is a new instance.
That means that in EF-core 2, the statements _dbSet.Remove(entity) repeatedly marked the same Diag instance as deleted: i.e. attached it when not yet attached and set its state to Deleted. That's not a problem.
EF-core 3+ tries to attach different Diag instances with the same key, which fails.
Fortunately, in EF core 5 the earlier tracking behavior can be restored by using AsNoTrackingWithIdentityResolution.
var deletedDiag = _unitOfWork.GetRepository<DIAGNOSIS_DETAIL>()
.GetAll(c => c.Diag.CMS_CASE_ID == model.DiagnosisModel.CASE_ID)
.Include(i => i.Diag)
.AsNoTrackingWithIdentityResolution()
.ToList();

StructureMap 2.5.3 in .Net 4.5.2 Lazy Loading Question

We are stuck back in StructureMap 2.5.3, running on .Net 4.5.2. I'm writing an app using our Libs that
needs to startup and login using local data, and not hit the DB.
In our BootStrap StructureMap Calls, we Create a named object for the DB access classes like this
// need one for ADO for JCDC
x.BuildInstancesOf()
.AddInstances( z => z
.OfConcreteType()
.WithName( "JCDC" )
.SetProperty( y => y.ConnectStringName = "SybaseDB" )
.SetProperty( y => y.TimeOutStringName = "SybaseDBCommandTimeout" )
);
How do I Make this load Lazily?
I know there is in .net 4 and Func before that, and I've found simple examples
of how to use it, but I haven't wrapped my head around how to get the above code to load lazily
(When structure map inits it , it immediately connect to the DB, which fails offline)

C# / Postgres / FluentNHibernate : configuring npgsql throws NotSupportedException

Sometimes I really start wondering what's going on in my sourcecode:
I'm trying to connect to PostGres 9.0 using npgsql 2.0.11.0, which I'm damn sure I already did, but right now, my program throws a NotSupportedException as it steps into the following :
ISessionFactory sf = Fluently.Configure()
.Database(PostgreSQLConfiguration.PostgreSQL82
.ConnectionString(c => c
.Host("localhost")
.Port(5432)
.Database("cw")
.Username("cw")
.Password("mypass")))
.Mappings(x => x.FluentMappings.AddFromAssemblyOf<MyMapping>())
.BuildSessionFactory();
The Stacktrace is quite neat to look at: Just one line.
at NHibernate.Dialect.Dialect.GetDataBaseSchema(DbConnection connection) in d:\CSharp\NH\nhibernate\src\NHibernate\Dialect\Dialect.cs:Line 718.
I tried transcribing this to the following:
ISessionFactory sf = Fluently.Configure()
.Database(PostgreSQLConfiguration.PostgreSQL82
.ConnectionString(c => c.Is("Server=localhost;Port=5432;Database=cw;User Id=cw;Password=myPass;")))
.Mappings(x => x.FluentMappings.AddFromAssemblyOf<CardTemplateMapping>())
.BuildSessionFactory();
Still, the result's the same. Anybody had similar issues or - even better - a fix?
I guess I'll end up holding a record for the most self-answered questions.
It needed the hbm2ddl.keywords property set to none. Now it works like a charm.
Cheers!
.Database(PostgreSQLConfiguration.PostgreSQL82
.Raw("hbm2ddl.keywords","none"));
See that you already found a solution. So just for some background:
The "none" will disable any operation regarding RDBMS KeyWords.
And the Keywords is available for MsSQL, Oracle, Firebird, MsSqlCe, MySQL, SQLite, SybaseAnywhere.
Since Postgress is not in the list it has to be set to None.
There is som info on it here: Quoting column names with NHibernate and PostgreSQL

Starting with NHibernate

I'm having major difficulties to start off with NHiberante.
Main problems:
Where my hbm.xml files should reside? I create a Mappings folder but I received an error "Could not find xxx.hbm.xml file."
I tried to load the specific class through the dialect cf.AddClass(typeof(xxx)); but it still gives me the same error (the files are marked as embebed resources.
Also I'm having major problems in connection to it. I stopped trying to use the cfg xml file and tried a more direct approach with a library I have here.
Configuration cfg = new Configuration();
cfg.AddClass(typeof(Tag));
ISessionFactory sessions = cfg.BuildSessionFactory();
AgnosticConnectionHandler agch = new AgnosticConnectionHandler("xxx","xxx","geo_biblio","localhost",
5432,DatabaseInstance.PostgreSQL);
ISession sessao = sessions.OpenSession(agch.GetConnection);
ITransaction tx = sessao.BeginTransaction();
Tag tag1 = new Tag();
tag1.NomeTag = "Teste Tag NHibernate!!!";
sessao.Save(tag1);
tx.Commit();
sessao.Close();
Any tips for me? I'm getting the exception in line 2 of this code, and still not sure what to do.
Any help is appreciated. Thanks
If you're starting with nHibernate I think you really should take a look at fluent nhibernate, its way easier do develop and maintain the mapping, it even has an auto-mapping option.
Another option is confORM from Fabio Maulo (nhibernate lead developer), looks like a great tool.
Also, you can take a look at s#arp architecture, you can get some nice ideas from this project.

NHibernate SchemaExport does not create tables when "script" is false

Making my first steps with NHibernate, I'm trying to have it creating my Tables automatically from the hbm files. The database backend is SQL Server 2008 Developer Edition.
This is the common sample code I see in NHibernate Tutorials:
var cfg = new Configuration();
cfg.Configure();
cfg.AddAssembly(typeof(Posting).Assembly);
new SchemaExport(cfg).Execute(false,true,false,false);
Sadly, this does not work. I have set show_sql to true, and it does not print out any statement. Looking at SQL profiler I see my Application connecting to the DB, but then doing nothing.
I can fix that by changing the first parameter ("script") to true:
new SchemaExport(cfg).Execute(true,true,false,true);
I don't understand why. The parameters of SchemaExport are sadly not really explained (also not the difference between .Create and .Execute), and I would like to find out what this parameter does, and why it's not needed i.e. when using SQL Compact Edition (that works also when script is false)
The SchemaExport is part of the Hbm2Ddl utility which is really separate from NHibernate functionality. It does not use "show_sql" which is used while NHibernate is running only.
To get a copy of the schema you create you use .SetOutputFile(filename)
This is the method I use when I wish to create a new database.
I get a formatted schema in MyDDL.sql file and the database is built from the schema:
private void BuildSchema(Configuration config)
{
new SchemaExport(config)
.SetOutputFile(_fileName + "MyDDL.sql")
.Execute(true /*script*/, true /*export to db*/,
false /*just drop*/, true /*format schema*/);
}
SchemaExport.Create is just a shortcut to Schema.Execute with the just drop false and format true.
public void Create(bool script, bool export)
{
Execute(script, export, false, true);
}

Categories