How can i configure fluent nHibernate connection properties - fluent-nhibernate

Can someone tell he how i can setup my fluent nhibernate connection to always connect as follows
SET NOCOUNT ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT ON
this is what i have at the moment
var fluentConfiguration = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(ConnectionString).ShowSql());
fluentConfiguration = fluentConfiguration.Cache(c => c
.UseQueryCache()
.UseMinimalPuts()
.ProviderClass<HashtableCacheProvider>());
thanks
Niall

Well your can customize that in DriverConnectionProvider. Custome properties how set numer... etc is for session so you could do it using driverconnectionproperties
public class ContextConnectionDriver : DriverConnectionProvider
{
public override IDbConnection GetConnection()
{
var conn = base.GetConnection();
SetContext(conn);
return conn;
}
private void SetContext(IDbConnection conn)
{
string const COMMAND_TEXT = "SET NOCOUNT ON;SET ARITHABORT ON;SET NUMERIC_ROUNDABORT ON;";
var cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = COMMAND_TEXT;
cmd.ExecuteNonQuery();
}
}
Set the NHibernate property connection.provider to <namespace>. ContextConnectionDriver, <assembly>
,to set the namespace and assembly according to the name of your project.
References Nhibernate 3.0 cookbook

Related

How to use a Oracle database in ASP.NET without Entity Framework?

Can someone tell me in a simple way, how can I use an Oracle DB in my ASP.NET MVC 5 project? I have tried different articles but I didn't get a clear answer...
I think this is the simple way to do this:
using System.Data.OracleClient;
public string GetConnectionString()
{
String connString = "SERVER=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=YourHostName)(PORT=YourPort))(CONNECT_DATA=(SERVICE_NAME=YourServiceName)));uid=YourUserId;pwd=YourPassword;";
return connString;
}
public void ConnectingToOracle()
{
string connectionString = GetConnectionString();
using (OracleConnection connection = new OracleConnection())
{
connection.ConnectionString = connectionString;
connection.Open();
OracleCommand command = connection.CreateCommand();
string sql = "select * from MyDatabase where name like '%John Paul%'";
command.CommandText = sql;
OracleDataReader reader = command.ExecuteReader();
while (reader.Read())
{
string myField = (string)reader["address"]; //Get the address of John Paul
}
}
}

Stored Procedure in Orchard

Hi We are working on a project and i am trying to call a stored procedure. I have searched for the solution but i didn't find any way that how to call a stored procedure so can any one please tell me how to execute stored procedure.
How ever finally i am using the below code to execute the stored procedure and get the result.
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Suppress))
{
// temporary scope for new connection and setting stored procedure, parameters, and return RecordName list
using (SqlConnection cn = new SqlConnection(_settingsManager.LoadSettings().First().DataConnectionString))
{
if (cn.State == ConnectionState.Closed)
{
cn.Open();
}
const string storedProcedure = "usp_spName";
SqlCommand cmd = new SqlCommand(storedProcedure, cn);
cmd.Parameters.AddWithValue("#IsVerified", "value");
cmd.Parameters.AddWithValue("#page", "value");
// for out put parameter
cmd.Parameters.AddWithValue("#totalRows", 0);
cmd.Parameters["#totalRows"].Direction = ParameterDirection.Output;
cmd.CommandType = CommandType.StoredProcedure;
IDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
// To Get The Values of the result
int id=Convert.ToInt32(reader["Id"].ToString());
}
reader.Close();
try
{
// To Get the Out Put Perameter
totalRecords = (int)cmd.Parameters["#totalRows"].Value;
}
catch
{
totalRecords = 0;
}
cmd.Parameters.Clear();
cmd.Dispose();
cn.Close();
}
}
actually, I don't know about stored procedures, but you can call stored functions using code like examaple below. I'm new to C# and orchard, so may be my approach is not correct and good enough. At first you should get ISessionLocator object instance, using IOrchardServices, then create NHibernate ISession instance and then IQuery/ISQLQuery with CreateSQLQuery().
here is example code of Services class
public class ExampleService {
private readonly IOrchardServices _oServices;
public EParamsServices(IOrchardServices oServices) {
_oServices = oServices;
}
public float GetRegionPopulationDencity(int rId){
//resolve ISession locator (you can do this using dependencies in ctor)
ISessionLocator sl = _oServices.WorkContext.Resolve<ISessionLocator>();
//create session
ISession _session = sl.For(null);
// create raw SQL query
return _session.CreateSQLQuery(#"SELECT data.RegionDencity(:rId) as result")
.AddScalar("result", NHibernateUtil.Single)
.SetParameter<int>("rId", rId)
.List<float>()
.FirstOrDefault<float>();
}
}
I think you can exec stored procs the same way, just change SQL code do exec yourProcName and ExecuteUpdate() instead of List() method (I'm not sure in this part)
you also should add reference to NHibernate assembly to your project and add NHibernate & Orchard.Data to your using part.
You have to reference NHibernate and System.Data in your module , then you can use the below code
var cmd = _transactionManager.GetSession().Connection.CreateCommand();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "MyStoredProcedure";
_transactionManager.GetSession().Transaction.Enlist(cmd);
cmd.ExecuteNonQuery();

how to enable SQL Application Role via Entity Framework

I'm now developing big government application with entity framework. at first i have one problem about enable SQL application role. with ado.net I'm using below code:
SqlCommand cmd = new SqlCommand("sys.sp_setapprole");
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = _sqlConn;
SqlParameter paramAppRoleName = new SqlParameter();
paramAppRoleName.Direction = ParameterDirection.Input;
paramAppRoleName.ParameterName = "#rolename";
paramAppRoleName.Value = "AppRole";
cmd.Parameters.Add(paramAppRoleName);
SqlParameter paramAppRolePwd = new SqlParameter();
paramAppRolePwd.Direction = ParameterDirection.Input;
paramAppRolePwd.ParameterName = "#password";
paramAppRolePwd.Value = "123456";
cmd.Parameters.Add(paramAppRolePwd);
SqlParameter paramCreateCookie = new SqlParameter();
paramCreateCookie.Direction = ParameterDirection.Input;
paramCreateCookie.ParameterName = "#fCreateCookie";
paramCreateCookie.DbType = DbType.Boolean;
paramCreateCookie.Value = 1;
cmd.Parameters.Add(paramCreateCookie);
SqlParameter paramEncrypt = new SqlParameter();
paramEncrypt.Direction = ParameterDirection.Input;
paramEncrypt.ParameterName = "#encrypt";
paramEncrypt.Value = "none";
cmd.Parameters.Add(paramEncrypt);
SqlParameter paramEnableCookie = new SqlParameter();
paramEnableCookie.ParameterName = "#cookie";
paramEnableCookie.DbType = DbType.Binary;
paramEnableCookie.Direction = ParameterDirection.Output;
paramEnableCookie.Size = 1000;
cmd.Parameters.Add(paramEnableCookie);
try
{
cmd.ExecuteNonQuery();
SqlParameter outVal = cmd.Parameters["#cookie"];
// Store the enabled cookie so that approle can be disabled with the cookie.
_appRoleEnableCookie = (byte[]) outVal.Value;
}
catch (Exception ex)
{
result = false;
msg = "Could not execute enable approle proc." + Environment.NewLine + ex.Message;
}
But no matter how much I searched I could not find a way to implement on EF.
Another question is: how to Add Application Role to Entity data model designer?
I'm using the below code for execute parameter with EF:
AEntities ar = new AEntities();
DbConnection con = ar.Connection;
con.Open();
msg = "";
bool result = true;
DbCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = con;
var d = new DbParameter[]{
new SqlParameter{ ParameterName="#r", Value ="AppRole",Direction = ParameterDirection.Input}
, new SqlParameter{ ParameterName="#p", Value ="123456",Direction = ParameterDirection.Input}
};
string sql = "EXEC " + procName + " #rolename=#r,#password=#p";
var s = ar.ExecuteStoreCommand(sql, d);
When run ExecuteStoreCommand this line return error:
Application roles can only be activated at the ad hoc level.
I do it the following way (assuming Database First):
I create the DbContext from the db and call it MyEntitiesBase
I inherit from MyEntitiesBase to create MyEntities with the following code:
public partial class MyEntities : MyEntitiesBase
{
private byte[] appRoleCookie;
private void SetAppRole()
{
try
{
appRoleCookie = Database.SqlQuery<byte[]>(
#"
DECLARE #cookie VARBINARY(8000)
DECLARE #r INT
EXEC sp_setapprole 'user', 'pass', #fCreateCookie = true, #cookie = #cookie OUTPUT
SELECT #cookie").First();
}
catch
{
throw new AuthenticationException();
}
}
private void UnSetAppRole()
{
bool failed = Database.SqlQuery<bool>("DECLARE #result BIT; EXEC #result = sp_unsetapprole #cookie = " + appRoleCookie.ToHexadecimalString() + "; SELECT #result").First();
if (failed)
throw new SecurityException();
}
public MyEntities() : base()
{
Database.Connection.Open();
SetAppRole();
}
private bool disposed = false;
protected override void Dispose(bool disposing)
{
if (disposed)
return;
UnSetAppRole();
Database.Connection.Close();
disposed = true;
base.Dispose(disposing);
}
}
Where ToHexadecimalString is an extension method for IEnumerable<byte>, as follows:
public static class BytesExtensions
{
public static string ToHexadecimalString(this IEnumerable<byte> bytes)
{
return "0x" + string.Concat(bytes.Select(b => b.ToString("X2")));
}
}
And that's it. Works with connection pooling on and everything. You just use this inherited version instead of the one generated by EF.
Basically what you are doing is calling a stored procedure.
Entity Framework has functionality to excute stored procedures. Here is an explaination with a video: http://msdn.microsoft.com/en-us/data/gg699321.aspx
If your scrol down to the section "Using Import Functions to Map Stored Procedures" you will find the part that is relevant for you.

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.

ALTER DB error when the connection string has an instance name - C# 4.0

I have a service written in C# that runs under the domain admin account. This account is set as SQL admin on all the SQL Servers in that domain. The service needs to copy a mdf/ldf (SQL server 2003 or 2008) from one server to another and attach it to the new server. Instead of detaching the DB at the source server, I am changing the DB status to read only, and then copying the mdf/ldf files. Once they get copied over, I reset the DB status to read-write.
This is working if the source server name is something like MYSQLSERVER2K8. However, the code does not work if it is an instance name. For example: MYSQLSERVER2K8\VAULT. I have run the unit tests in NUnit on my code and the unit tests pass for both cases. However, the service is unable to change the DB status. The error we get is as follows:
SQL: ALTER DATABASE My_Test_DataBase SET SINGLE_USER WITH ROLLBACK IMMEDIATE ---> System.Data.SqlClient.SqlException: Database 'My_Test_DataBase' does not exist. Check sysdatabases. ALTER DATABASE statement failed. at System.Data.SqlClient.SqlConnection.
Here is my code (note that I am converting the server name to the IP address in the connection string. For example: MYSQLSERVER2K8\VAULT gets converted to 111.111.111.111\VAULT:
#region ChangeDatabaseStatus
/// <summary>
/// Change the database status to read-only/read-write
/// </summary>
/// <param name="serverName"></param>
/// <param name="databaseName"></param>
/// <param name="status"></param>
public virtual bool ChangeDatabaseStatus(string serverName, string databaseName, string status)
{
DateTime beginTimeStamp = DateTime.Now;
string sql = String.Empty;
bool databaseStatusChanged = false;
try
{
SqlConnection connection = GetSqlConnection(false);
string connectionString = connection.ConnectionString;
string serverIPAddress = Dns.GetHostAddresses(serverName.Contains(#"\") ? serverName.Substring(0, serverName.IndexOf(#"\")) : serverName)[0].ToString();
connectionString = connectionString.Replace("{0}", serverIPAddress = serverName.Contains(#"\") ? serverIPAddress + serverName.Substring(serverName.IndexOf(#"\"), serverName.Length - serverName.IndexOf(#"\")) : serverIPAddress);
connection.Close();
connection = new SqlConnection(connectionString);
using (SqlCommand command = new SqlCommand())
{
command.Connection = connection;
command.CommandTimeout = _commandTimeout;
command.CommandType = CommandType.Text;
command.CommandText = String.Format("ALTER DATABASE {0} SET SINGLE_USER WITH ROLLBACK IMMEDIATE", databaseName);
//Debugging & Exception handling
sql = HelperFunctions.BuildSQL(command);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
using (SqlCommand command = new SqlCommand())
{
command.Connection = connection;
command.CommandTimeout = _commandTimeout;
command.CommandType = CommandType.Text;
command.CommandText = status == "ReadOnly" ? String.Format("ALTER DATABASE {0} SET READ_ONLY", databaseName) : String.Format("ALTER DATABASE {0} SET READ_WRITE", databaseName);
//Debugging & Exception handling
sql = HelperFunctions.BuildSQL(command);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
databaseStatusChanged = true;
}
using (SqlCommand command = new SqlCommand())
{
command.Connection = connection;
command.CommandTimeout = _commandTimeout;
command.CommandType = CommandType.Text;
command.CommandText = String.Format("ALTER DATABASE {0} SET MULTI_USER", databaseName);
//Debugging & Exception handling
sql = HelperFunctions.BuildSQL(command);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
catch (Exception e)
{
throw new DataProviderException(String.Format("{0} operation failed. SQL: {1}", MethodBase.GetCurrentMethod().Name, sql), e);
}
finally
{
LogPerformance(String.Format("Elapsed time for: {0}", MethodBase.GetCurrentMethod().Name), beginTimeStamp, DateTime.Now, null);
}
return databaseStatusChanged;
}
#endregion //ChangeDatabaseStatus
Check you don't have an alias configured.
Load the Sql Server Configuration Manager, under Native Client, then Aliases.
As Tony Hopkinson says, test you can connect using sqlcmd or something from the same machine:
sqlcmd -S MYSQLSERVER2K8\VAULT -q "ALTER DATABASE dbname SET SINGLE_USER WITH ROLLBACK IMMEDIATE"