Is there a way to generate mappings for NHibernate from POCO? This reply to my question makes NHibernate look very interesting. However i have a lot of classes that look like this
public class register_email_job
{
public PK id;
public user_data user;
}
public class user_comment : BaseComment2
{
[IsNullable]
public user_comment parent;
public user_data user;
}
I would like to easily translate this into something compatible with NHibernate. I wouldnbt mind modifying some queries but i prefer not to rewrite each class to use properties and modify class in such a way i need to change how its used everywhere.
-edit- Note that i use inheritance and user_comment has an object to user_comment (thus why it must be nullable. so it doesn't infinitely recurse. null is root).
You may want to take a look at the Auto Mapping abilities of Fluent NHibernate: http://wiki.fluentnhibernate.org/Auto_mapping
In order for NHibernate to construct proxies for your entity classes, you will need to make your non-private members virtual. Public fields will not work with proxy objects, these should be converted to properties.
public class register_email_job
{
public virtual PK id { get; set; }
public virtual user_data user { get; set; }
}
Fluent NHibernate is able to create mapping from classes. It can automap based on conventions, or you can write your own mappers.
Your entities and tables may not match the default conventions, there a several ways to override them.
Using classmap, your mapping might look like this:
public class register_email_job_map : ClassMap<register_email_job>
{
public register_email_job_map()
{
Id( x => x.Id );
References( x=> x.user );
}
}
public class user_comment_map : ClassMap<user_comment>
{
public register_email_job_map()
{
// properties from BaseComment2
References( x=> x.user );
References( x=> x.parent );
}
}
Related
I've got a domain model structured like this:
public class Foo
{
private readonly HashSet<int> _intSet;
public IReadOnlySet<int> Intset => _intSet;
public Foo(HashSet<int> intSet)
{
_intSet = intSet;
}
}
Now, I'd like to use EF's Fluent API to persist it, but I keep getting the InvalidOperationException stating that:
No suitable constructor was found for entity type 'Foo'. The following constructors had parameters that could not be bound to properties of the entity type: cannot bind 'intSet' in 'Foo(HashSet<int> intSet).'
I've tried using the ModelBuilder options shown below, unfortunatelly to no avail:
modelBuilder
.Entity<Foo>()
.Property(p => p.Intset)
.HasField("_intSet")
.UsePropertyAccessMode(PropertyAccessMode.FieldDuringConstruction);
Is there any actual way to make this work? Note that I definitely do not want to use DataAnnotations.
EF models should have a parameterless constructor
Something like this should work:
public class Foo
{
public Hashset<int> Intset { get; set;}
}
But you will lose that read-only policy.
If you want to keep that feature you should make some DTO class which would look like this
public class FooDto
{
private readonly HashSet<int> _intSet;
public IReadOnlySet<int> Intset => _intSet;
public FooDto(HashSet<int> intSet)
{
_intSet = intSet;
}
}
and then use that DTO with some mapping in vanilla style like this (or use mapping library like Automapper)
var fooDto = new FooDto(foo.Intset);
I have two class BookingInfo.cs and BookingTransaction class.
public class BookingInfo
{
public virtual string Code { get; set; }
}
public class BookingTransaction : BookingInfo {
public virtual string CustomerRefNo { get; set; }
}
below is the NHibernate mapping for both classes
public class BookingInfoConfiguration : ClassMap<BookingInfo> {
public BookingInfoConfiguration() {
Table("Bkg_BookingInfo");
LazyLoad();
DynamicUpdate();
Id(x => x.Id).GeneratedBy.GuidComb().UnsavedValue(Guid.Empty);
}
}
public class BookingTransactionConfiguration :
ClassMap<BookingTransaction> {
public BookingTransactionConfiguration() {
Table("Bkg_BookingInfo");
LazyLoad();
DynamicUpdate();
Id(x => x.Id).GeneratedBy.GuidComb().UnsavedValue(Guid.Empty);
}
}
Now i am querying to get rows from database.
CurrentSession.Query<BookingInfo>().ToList();
I get two items for single row in database table. one for Bookinginfo and another for BookingTransaction. but i want to get only result of type Bookinginfo.
How to remove the items of the child class from the result?
As said in Rabban's answer, this is by design. This is called implicit polymorphism. Rabban propose you to change your class hierarchies, but you can instead disable implicit polymorphism if you prefer.
With hbm mappings (I do not use fluent and do not know it), add the attribute polymorphism="explicit" on your class.
Mapping by code supports it too on class mapper with .Polymorphism(PolymorphismType.Explicit).
You can read more about implicit/explicit polymorphism here:
Implicit polymorphism means that instances of the class will be
returned by a query that names any superclass or implemented interface
or the class and that instances of any subclass of the class will be
returned by a query that names the class itself. Explicit polymorphism
means that class instances will be returned only be queries that
explicitly name that class and that queries that name the class will
return only instances of subclasses mapped inside this <class>
declaration as a <subclass> or <joined-subclass>. For most purposes
the default, polymorphism="implicit", is appropriate. Explicit
polymorphism is useful when two different classes are mapped to the
same table (this allows a "lightweight" class that contains a subset
of the table columns).
Its intended that NHibernate returns you both objects. To prevent this behavior create a abstract base class where both other class derive. Then you don't need to duplicate code and you can query each class separately.
Create the base class:
public abstract class BookingBase
{
public virtual string Code { get; set; }
}
and then derive your classes from it:
public class BookingInfo : BookingBase
{
}
public class BookingTransaction : BookingBase
{
public virtual string CustomerRefNo { get; set; }
}
Your mappings and queries can remain the same. And if you want to query both classes with one query, just query BookingBase.
I'm having problems developing a sane set of Fluent NHibernate mappings for the following model structure:
public class BaseLookup
{
public virtual int Id {get; set;}
public virtual string Code {get; set;}
public virtual string Value {get; set;}
public virtual bool Active {get; set;}
}
public class Subdivision : BaseLookup { }
public class AvisCode : BaseLookup { }
public class District : BaseLookup { }
/*etc.*/
These lookups all share properties, but otherwise have no relationship to each other. These tables have special semantic meanings for reports and will be referenced specifically in stored procedures, so I don't wish to mash them into a common 'lookups' table that would require me to use a discriminator. That seems to eliminate Table-per-Hierarchy and Table-per-Sublass strategies in my mappings. I'm also having difficulty employing Table-per-Concrete-Class because each lookup has its own identity column - I do not want to have to assign an Id manually in the application, and there's no requirement for Id's to be unique across all these tables.
My mappings, at the moment, look like this, and are identical for each superclass of BaseLookup:
public class AvisCodeMap : ClassMap<AvisCode>
{
public AvisCodeMap()
{
Schema(Schemas.pva.ToString());
Id(x => x.Id).GeneratedBy.Identity();
Map(x => x.Code).Not.Nullable();
Map(x => x.Value).Not.Nullable();
}
}
Is there no mapping convention that allows me to extract the repetitive mappings to a block of re-usable code?
If I understand your question right, you might need to create a generic base class map then reuse it in derived maps.
Example as follows:
public class BaseLookupMap<T> : ClassMap<T> where T : BaseLookup
{
public BaseLookupMap()
{
// ... base mapping code goes here ...
}
}
To create that base type:
public class BaseLookupMap : BaseLookupMap<BaseLookup>
{
}
And the derived class map:
public class AvisCodeMap : BaseLookupMap<AvisCode>
{
public AvisCodeMap()
{
Polymorphism.Explicit();
// ... your other mappings here, if needed ...
}
}
HTH.
Using the Code First approach I have created a number of different entities that inherit from an interface IConcurrent with a property IsActive for example:
public class Currency : IConcurrent
{
public string CurrencyId { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
}
Each time I select entities I find myself always having to include a conditional clause such as this real basic example:
db.Currencies.Where(c => c.IsActive);
My question is that is it possible to some how intercept/hook into the DbContext so that my LINQ queries will always return IsActive == true for entities that inherit the IConcurrent interface, to avoid having to explicitly add .Where(c => c.IsActive) each time?
So far I've looked at the possible methods to override in DbContext which none of them seem to fit the bill. Can anyone help?
You can use filtering on the Set<> method to get just active instances, something along the lines of:
public IQueryable<T> GetActive<T>() where T : class, IConcurrent
{
return Set<T>().Where(e => e.IsActive);
}
This method could be included in a class that inherits the DbContext class, or you could make it into an extension method, like:
public static DbContextExtensions
{
public static IQueryable<T> GetActive<T>(this DbContext context)
where T : class, IConcurrent
{
return context.Set<T>().Where(e => e.IsActive);
}
}
Conditional mapping is supported in Model First approach but it is not directly supported in Code first approach. You may have a workaround by creating a property in DBContext similar to the following;
public IQueryable<Currency> ActiveCurrencies
{
get
{
db.Currencies.Where(c => c.IsActive);
}
}
Lets say I have two classes:
public class A
{
public virtual int Id { get; set; }
public virtual Object1 Obj { get; set; }
}
public class B : A
{
public new virtual Object2 Obj { get; set; }
}
I use Fluent NHibernate and I have created two different mappings for the two classes. However, when I try to query class A in my repository, FNH finds both class B and A, which kind of makes sense since both are A.
Example (this criteria will query over both A and B):
public List<T> GetByName(string name)
{
return Session.CreateCriteriaOf<A>.Add(Restrictions...);
}
When writing CreateCriteriaOf<A>, I only want to query over A - not B. How can I solve my problem?
I think you better make an inheritance tree where both A and B derive from a common (abstract) base type. Then NHibernate can make the distinction by a discriminator column.
Of course, your data model should accommodate this, so I hope your model is not prescribed in any way.