Get table names from Fluent Nhibernate - fluent-nhibernate

After you have setup your mappings in fluent nhibernate, is there a way of getting the table name for an entity from the class type?
I have read in regular nhiberante you can do something like cfg.GetClassMapping(typeof (Employee)). I would like to do the type of thing to retrieve the database table name.
Is this possible as standard or how would I go about this?

The fluent nhibernate way:
var userMetadata = sessionFactory.GetClassMetadata(typeof(SomeEntity)) as NHibernate.Persister.Entity.AbstractEntityPersister;
var cols = userMetadata.KeyColumnNames;
var table = userMetadata.TableName;
where sessionFactory is of type ISessionFactory.

Assuming you have done this at some point:
FluentNHibernate.Cfg.FluentConfiguration fluentConfig = FluentNHibernate.Cfg.Fluently.Configure();
Then all you have to do is this:
string tableName = fluentConfig.BuildConfiguration().GetClassMapping(typeof (One of your data entities)).Table.Name;
Worked great in my implementation of a generic "GetAllItems" routine.

Hi I'm using this to create Full Text Catalogs on M$ Sql Server, using almost same mechanism of FluentNhibernate mapping.
From Configuration I get a list of persistentClasses
this.persistenClasses = configuration.ClassMappings;
Next I search through this list to find my persistenClass class by its Generic type of mapping class
var genericDefinition = mappingClass.BaseType.GetGenericArguments()[0];
var matchedPersistClass = FindPersistedClassFrom(genericDefinition);
private PersistentClass FindPersistedClassFrom(Type genericDefinition)
{
return persistentClasses.FirstOrDefault(x => x.EntityName == genericDefinition.FullName);
}
So having persistentClass you easily have access to Table Name, properties, db fields, etc.
TableName = matchedPersistClass.Table.Name,

cfg.GetClassMapping(typeof(Employee)).Table.Name will also work, and seems to be much simpler.

Related

RepoDb cannot find mapping configuration

I'm trying to use RepoDb to query the contents of a table (in an existing Sql Server database), but all my attempts result in an InvalidOperationException (There are no 'contructor parameter' and/or 'property member' bindings found between the resultset of the data reader and the type 'MyType').
The query I'm using looks like the following:
public Task<ICollection<MyType>> GetAllAsync()
{
var result = new List<MyType>();
using (var db = new SqlConnection(connectionString).EnsureOpen())
{
result = (await db.ExecuteQueryAsync<MyType>("select * from mytype")).ToList();
}
return result;
}
I'm trying to run this via a unit test, similar to the following:
[Test]
public async Task MyTypeFetcher_returns_all()
{
SqlServerBootstrap.Initialize();
var sut = new MyTypeFetcher("connection string");
var actual = await sut.GetAllAsync();
Assert.IsNotNull(actual);
}
The Entity I'm trying to map to matches the database table (i.e. class name and table name are the same, property names and table column names also match).
I've also tried:
putting annotations on the class I am trying to map to (both at the class level and the property level)
using the ClassMapper to map the class to the db table
using the FluentMapper to map the entire class (i.e. entity-table, all columns, identity, primary)
putting all mappings into a static class which holds all mapping and configuration and calling that in the test
providing mapping information directly in the test via both ClassMapper and FluentMapper
From the error message it seems like RepoDb cannot find the mappings I'm providing. Unfortunately I have no idea how to go about fixing this. I've been through the documentation and the sample tutorials, but I haven't been able to find anything of use. Most of them don't seem to need any mapping configuration (similar to what you would expect when using Dapper). What am I missing, and how can I fix this?

fetch single property in object from database

I am working on NET MVC 3.0 and Nhibernate 3.0. I want to fetch only one property from database to an object.
For instance, suppose I have a class Module. I want to select all the names from module table (like select modulename from module query) and an prepare a list of module objects which have only name. All other properties can be null.
I tried this using QueryOver API:
IQueryOver<ProjectModule> module = session.QueryOver<ProjectModule>()
.Select(a=>a.Name)
.TransformUsing(
NHibernate.Transform.Transformers.AliasToBean<ProjectModule>());
pm = module.List<ProjectModule>();
pm is IList<ProjectModule> type.
Transaction gets committed successfully. No error occurred, but I get a list of module objects with all properties = null. Module name null, module id null etc.
I checked what query is executing on SQL using NUnit and got this: SELECT this_Name as y0_ FROM ProjectModule this_.
To be more accurate create a DTO object, assume ProjectModuleDto, that will contain only the Name. It's not a good practice to use the the domain object with uninitialized values through your code, cause it creates confusions of filled data in various scenarious.
And the fllowing code will do the trick - populate the list of DTOs: ProjectModuleDto with correct Name of project module from database:
ProjectModuleDto projectModuleDto = null;
IQueryOver<ProjectModule> module = session.QueryOver<ProjectModule>()
.SelectList(
list=>list.Select(a => a.Name).WithAlias(() => projectModuleDto.Name)
)
TransformUsing(NHibernate.Transform.Transformers.AliasToBean<ProjectModuleDto>());
pm = module.List<ProjectModuleDto>();
If you are fetching only a single property, you don't need to use transformers. Try to use a List<string> directly:
var moduleNames = session.QueryOver<ProjectModule>()
.Select(a => a.Name)
.List<string>();
Read more about QueryOver syntax on NHibernate blog.
Is this what you're looking for?
List<ProjectModule> result = new List<ProjectModule>();
session.QueryOver<ProjectModule>()
.Select(a => a.Name)
.ToList().ForEach(delegate(string mName)
{
result.Add(ProjectModule() { Name = mName });
});

How to display only specific columns of a table in entity framework?

how to display the some specific columns of table instead of whole table in entity framework.
using (DataEntities cxt = new DataEntities())
{
notes note = cxt.notes.Where(no => no.id == accID).SingleOrDefault();
return notes;
}
For this purpose, I would suggest you to make use of ViewModel like following :-
notes note = cxt.notes.SingleOrDefault(no => no.id == accID);
var model = new YourViewModel // Your viewModel class
{
ID = note.ID,
PropertyOne = note.PropertyOne, // your ViewModel Property
PropertyTwo = note.PropertyTwo
};
You can do this with QueryView.
This implies editing your model directly in XML as there is no designer support for this, but you will get an independant entity with less fields than the original one.
Advantages:
You can then query data base for this truncated entity directly (you will get only fields you need from the data base - no need to get whole entity from DB and trancate it in code)
It is good in scenarios where you want to send this truncated entity to the
client
with WCF to minimize traffic (e.g. when building big lists on client
that basically need only name and ID and no other entity specific
information).
Disadvantages:
This QueryView-based entity is read only. To make it writeable you will have to add r/w functionality yourself

NHibernate: How to get mapped values?

Suppose I have a class Customer that is mapped to the database and everything is a-ok.
Now suppose that I want to retrieve - in my application - the column name that NH knows Customer.FirstName maps to.
How would I do this?
You can access the database field name through NHibernate.Cfg.Configuration:
// cfg is NHibernate.Cfg.Configuration
// You will have to provide the complete namespace for Customer
var persistentClass = cfg.GetClassMapping(typeof(Customer));
var property = persistentClass.GetProperty("FirstName");
var columnIterator = property.ColumnIterator;
The ColumnIterator property returns IEnumerable<NHibernate.Mapping.ISelectable>. In almost all cases properties are mapped to a single column so the column name can be found using property.ColumnInterator.ElementAt(0).Text.
I'm not aware that that's doable.
I believe your best bet would be to use .xml files to do the mapping, package them together with the application and read the contents at runtime. I am not aware of an API which allows you to query hibernate annotations (pardon the Java lingo) at runtime, and that's what you would need.
Update:
Judging by Jamie's solution, NHibernate and Hibernate have different APIs, because the Hibernate org.hibernate.Hibernate class provides no way to access a "configuration" property.

NHibernate - How do I change schemas during run time?

I'm using NHibernate to connect to an ERP database on our DB2 server. We have a test schema and a production schema. Both schemas have the same table structure underneath. For testing, I would like to use the same mapping classes but point NHibernate to the test environment when needed and then back when in production. Please keep in mind that we have many production schemas and each production schema has an equivalent test schema.
I know that my XML mapping file has a schema property inside it, but since it's in XML, it's not like I can change it via a compiler directive or change the schema property based on a config file.
Any ideas?
Thank You.
No need to specify schema in the mappings: there's a SessionFactory-level setting called default_schema. However, you can't change it at runtime, as NHibernate pregenerates and/or caches SQL queries, including the schema part.
To get what I wanted, I had to use NHibernate.Mapping.Attributes.
[NHibernate.Mapping.Attributes.Class(0, Table = “MyTable”, Schema = MySchemaConfiguration.MySchema)]
In this way, I can create a class like MySchemaConfiguration and have a property inside of it like MySchema. I can either set the property's value via a compiler directive or get it through a configuration file. This way I only have to change the schema in one place and it will be reflected throughout all of the other mappings.
I have found following link that actually fixes the problem.
How to set database schema for namespace in nhibernate
The sample code could be
cfg.ClassMappings.Where(cm => cm.Table.Schema == "SchemaName")
.ForEach(cm => cm.Table.Schema = "AnotherSchemaName");
This should happen before you initialize your own data service class.
#Brian, I tried NHibernate.Mapping.Attributes, the attribute value you put inside should be a constant. So it could not be updated during run time. How could you have set the property's value using a parameter value in configuration file?
The code to fix HBM XML resources.
// This is how you get all the hbm resource names.
private static IList<string> GetAllHbmXmlResourceNames(Assembly assembly)
{
var result = new List<string>();
foreach (var resource in assembly.GetManifestResourceNames())
{
if (resource.EndsWith(".hbm.xml"))
{
result.Add(resource);
}
}
return result;
}
// This is how you get the stream for each resource.
Assembly.Load(assembly).GetManifestResourceStream(name)
// What you need to do next is to fix schema name in this stream
// Replacing schema name.
private Stream FixSchemaNameInStream(Stream stream)
{
StreamReader strStream = new StreamReader(stream);
string strCfg = strStream.ReadToEnd();
strCfg = strCfg.Replace(string.Format("schema=\"{0}\"" , originalSchemaName), string.Format("schema=\"{0}\"" , newSchemaName));
return new MemoryStream(Encoding.ASCII.GetBytes(strCfg));
}
Take a look at SchemaUpdate.
http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/04/28/create-and-update-database-schema.aspx