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.
Related
i have a microservice api where I try to log all the request which come in...so the elasticsaerch service and kibana are on a different server. I'm using the serilog.sinks.elasticsearch package to send data to the elasticsearch.
Both servers are not running with docker, they are just normal windows server.
My code looks like this to setup the logging...
public static Logger Create(IConfiguration configuration)
{
var elasticsearchSection = configuration.GetSection("Elasticsearch");
if (elasticsearchSection != null)
{
return CreateLoggerConfiguration(elasticsearchSection).CreateLogger();
}
return null;
}
private static LoggerConfiguration CreateLoggerConfiguration(IConfigurationSection section)
{
var loggerConfiguration = new LoggerConfiguration();
var url = section.GetValue<string>("Url");
var minimumLogLevel = section.GetValue<string>("MinimumLogLevel");
var minimumLogEventLevel = section.GetValue<string>("MinimumLogEventLevel");
SetLoggerConfigurationMinimumLogLevel(minimumLogLevel, loggerConfiguration);
loggerConfiguration.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(GetLoggingUri(url))
{
MinimumLogEventLevel = ReturnLogEventLevel(minimumLogEventLevel),
AutoRegisterTemplate = true
});
loggerConfiguration.Enrich.FromLogContext();
return loggerConfiguration;
}
And in my startup,cs I'm using
services.AddLogging(loggingBuilder => loggingBuilder.AddSerilog(dispose: true));
in the ConfigureServices Method...
But apparently I cant create an Index inside my Kibana.
Any ideas why this isnt working?
I have a Windows Forms application. I want to create a setup file for this application. I used Visual Studio 2012 and SQL Server 12.
I want this setup to work in every new environment.
So, how do I make this connection string dynamic? Can I create a connection string after installation and make it available for every form to access, like in my local machine?
Any kind of source code, video links, explanations or examples will be a great help for me.
I propose to search on the machine for instances of the SQL server, and then in every instance search for the databases. You could setup some logic for example if only one instance is found, and on this instance only database with specific name exists then use this database, but if two or more instances are found, or different database name then preferred is found, show window to user where he can choose the right one.
To find Database instance you could use following method:
private static DataRowCollection SQLDataServers()
{
System.Data.Sql.SqlDataSourceEnumerator instance = System.Data.Sql.SqlDataSourceEnumerator.Instance;
DataTable dt = instance.GetDataSources();
if (dt.Rows.Count>0)
{
return dt.Rows;
}
throw new Exception("No SQL Instance Found");
}
To find tables in the database you can use following method:
private static List<string> GetDatabases(string conString)
{
List<string> list = new List<string>();
using (SqlConnection con = new SqlConnection(conString))
{
con.Open();
using (SqlCommand cmd = new SqlCommand("SELECT name from sys.databases", con))
{
using (IDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
list.Add(dr[0].ToString());
}
}
}
}
return list;
}
To generate connection string you can use nuget package or following methods:
public static string GetSqlDataSourceConnectionString(string dataSource)
{
return GetSQLDataSource(dataSource).ToString();
}
private static SqlConnectionStringBuilder GetSQLDataSource(string dataSource)
{
var r = GetDataSource(dataSource).AddIntegratedSecurity();
return r;
}
private static SqlConnectionStringBuilder GetDataSource(string dataSource)
{
SqlConnectionStringBuilder sqlBuilder = new
SqlConnectionStringBuilder();
sqlBuilder.DataSource = dataSource;
return sqlBuilder;
}
private static SqlConnectionStringBuilder AddIntegratedSecurity(this SqlConnectionStringBuilder connectionStringBuilder)
{
connectionStringBuilder.IntegratedSecurity = true;
return connectionStringBuilder;
}
The method which connects all this elements can be as following:
static void Main(string[] args)
{
var servers=SQLDataServers();
foreach (DataRow item in servers)
{
string serverName = string.Format($"{item.ItemArray[0].ToString()}\\{item.ItemArray[1].ToString()}");
var connectionString = GetSqlDataSourceConnectionString(serverName);
var listOfDB=GetDatabases(connectionString);
}
}
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);
}
}
It seems that altough I have been using NHibernate for a while now, I still misunderstand some basic concepts of this ORM. Let's say I have a class called "Blog" and I load a persisted instance like so:
using (var tx = Session.BeginTransaction())
{
var myBlog = Session.Get(10);
tx.Commit();
}
If I now change a property of this instance, NHibernate seems to automatically detect the unsaved changes and will produce an UPDATE on transaction-commit.
This causes, that the following statements do exactly the same:
using (var tx = Session.BeginTransaction())
{
var myBlog = Session.Get(10);
myBlog.Title = "Changed title";
tx.Commit();
}
using (var tx = Session.BeginTransaction())
{
var myBlog = Session.Get(10);
myBlog.Title = "Changed title";
Session.Update(myBlog); // why is this necessary?
tx.Commit();
}
I don't see any difference with NHProf. So why does the explicit Update-method exists and when should I use it?
Entities are not always connected with session. For example you could have webservice with method, that accepts some entity, and updates in db:
[WebMethod]
void UpdatePerson(int id, string name){
using (var tx = Session.BeginTransaction(){
var person = new Person(id, name);
Session.Update(person);
tx.Commit();
}
}
This code executes update in database without issuing select.
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