My database has multiple schemas, the fluent nhibernate faq states that you can specify schema for the entire database, or per entity. I want to specify schema per AutoPersitenceModel, can this be done?
Got it:
public class SchemaConvention : IClassConvention
{
public void Apply(IClassInstance instance)
{
instance.Schema("schemaName");
}
}
AutoPersistenceModel model = AutoMap.AssemblyOf<Whatever>();
model.Conventions.AddFromAssemblyOf<SchemaConvention>();
Related
I have the following model object in c# that I'm receiving in a WEB API from a POST - Does anyone know how I would write this object to a database? The tables can be whatever, I'm just not sure how to cycle through this model to get the 'Sequence', 'Quote' & 'Items' to flat files from objects.
public class PickupDetail
{ public string driver_name;
public class PickupDate
{
public DateTime pickup_date;
public class Sequence
{ ...Sequence fields
public class Quote
{ ...Quote fields
public class Item
{ ....Item fields
public class OriginalItem
{
...OriginalItem fields
}
public OriginalItem original;
}
public List<Item> items;
}
public List<Quote> quotes;
}
public List<Sequence> sequence;
}
public List<PickupDate> dates;
}
From information you are giving it is not obvious what would be the usage for the software you have but given that data I suggest you learn more about ORMs such as nHibernate.
Then configure your models using Fluent nHibernate. Then only thing you need to do is
_session.SaveOrUpdate(pickupDetail);
The ORM will take care of creation and/or updating of the nested properties.
I have some existing asp.net membership and roles tables in a legacy db and I am mapping them to new entities with Fluent Nhibernate.
I also generate the schema directly from Fluent Nhibernate and I then manually tweak the generated sql script to exclude the existing tables.
Is it possible to say to Fluent Nhibernate to exclude from generation certain tables?
SchemaAction.None() in your ClassMap.
Another option would be to create an attribute, say
public class DoNotAutoPersistAttribute : Attribute
{
}
Then in AutoPersistenceModelGenerator you could check for this attribute in the Where clause of AddEntityAssembly.
I've managed this with an attribute + convention:
public enum SchemaAction
{
None
}
[Serializable]
[AttributeUsage(AttributeTargets.Class)]
public class SchemaActionAttribute : Attribute
{
private readonly SchemaAction schemaAction = SchemaAction.None;
public SchemaActionAttribute()
{
}
public SchemaActionAttribute(SchemaAction schemaAction)
{
this.schemaAction = schemaAction;
}
public SchemaAction GetSchemaAction()
{
return schemaAction;
}
}
/// <summary>
/// overrides the default action for entities when creating/updating the schema
/// based on the class having a Schema attribute (<see cref="SchemaActionAttribute" />)
/// </summary>
public class SchemaActionConvention : IClassConvention
{
public void Apply(IClassInstance instance)
{
object[] attributes = instance.EntityType.GetCustomAttributes(true);
foreach (object t in attributes)
{
if (t is SchemaActionAttribute)
{
var a = (SchemaActionAttribute) t;
switch(a.GetSchemaAction())
{
case SchemaAction.None:
instance.SchemaAction.None();
return;
default: throw new ApplicationException("That schema action:" + a.GetSchemaAction().ToString() + " is not currently implemented.");
}
}
}
}
}
...
[SchemaAction(SchemaAction.None)]
public class TextItem : Entity
...
I have a IIdConvention for my Fluent NHibernate mapping:
public class SplitIDNameConvention : IIdConvention
{
public bool Accept(IIdentityPart target)
{
return true;
}
public void Apply(IIdentityPart target)
{
if (target.GetColumnName() == null)
target.ColumnName(SplitName(target.Property.Name));
}
}
This works perfect for tables with a single primary key, but I have a lot of tables with CompositeKeys. Is there a way to provide a Convetion which changes the mapped column name for CompositeIds in Fluent NHibernate?
Best regards,
forki
Not what you want to hear, but no, not currently.
In the project I'm working on now, we have base Entity class that looks like this:
public abstract class Entity<T> where T : Entity<T>
{
public virtual object Id { get; protected set }
// Equals, GetHashCode overrides, etc...
}
Most classes inheriting from Entity should map Id to int column in SQL Server database, but at least one will need to map to long (bigint).
Is it possible to create FluentNH Auto Mapping convention to map those object Ids to int by default? Then we could use another convention or IAutoMappingOverride to handle long Ids.
Thanks!
To answer my own question... It's possible.
You can define convention like this:
internal class PrimaryKeyConvention : IIdConvention
{
public bool Accept(IIdentityPart id)
{
return true;
}
public void Apply(IIdentityPart id)
{
if (<ID should be long>)
id.SetAttribute("type", "Int64");
else
id.SetAttribute("type", "Int32");
}
}
I have the following idea:
Business object implemented as interface or abstract class with certain properties as read only to all layers except the DAL layer. I also want my business objects in another assembly than the DAL (for testing purposes), so marking the properties is not an option for me.
Examples could be one to one relationships or other properties.
I have almost solved the issue by doing the following
abstract class User
{
public virtual long UserId {get; protected set;}
public virtual string Password {get; protected set;}
...
}
In the DAL:
public class DbUser : User
{
internal virtual void SetPassword(string password) {...}
}
I then map this using fluent as
ClassMap<User> {...}
SubclassMap<DbUser> {...}
The problem I get is that fluent tries to create a table named DbUser.
If I skip the SubclassMap and creates a DbUser object and tries to save it I get an "No persister for this object" error.
Is it possible to solve?
You could probably override what is done with Fluent
public class DbUser: IAutoMappingOverride<DbUser>
{
public void Override(AutoMapping<DbUser> mapping)
{
//tell it to do nothing now, probably tell it not to map to table,
// not 100% on how you'd do this here.
}
}
Or you could have an attribute
public class DoNotAutoPersistAttribute : Attribute
{
}
And in AutoPersistenceModelGenerator read for attribute in Where clause to exclude it.
Check would be something like
private static bool CheckPeristance(Type t) {
var attributes = t.GetCustomAttributes(typeof (DoNotAutoPersistAttribute), true);
Check.Ensure(attributes.Length<=1, "The number of DoNotAutoPersistAttribute can only be less than or equal to 1");
if (attributes.Length == 0)
return false;
var persist = attributes[0] as DoNotAutoPersistAttribute;
return persist == null;
}
Then it kind of depends how you're adding entities but you're probably adding via assembly so this might do it for you:
mappings.AddEntityAssembly(typeof(User).Assembly).Where(GetAutoMappingFilter);
....
...
private static bool GetAutoMappingFilter(Type t)
{
return t.GetInterfaces().Any(x => CheckPeristance(x)); //you'd probably have a few filters here
}