FluentNHibernate mapping syntax help needed - nhibernate

I'm having some trouble figuring out the appropriate FluentNHibernate mapping syntax for the following data model and domain objects. Here's the data model I'm working against:
And I'm trying to map the following domain objects to that model:
namespace FluentNHibernateSandbox.Entities
{
public abstract class EntityBase
{
public virtual long Id { get; set; }
}
}
namespace FluentNHibernateSandbox.Entities
{
public class Attribute : EntityBase
{
public virtual string Name { get; set; }
public virtual string Label { get; set; }
public virtual string Description { get; set; }
public virtual int SortOrder { get; set; }
public virtual Group Group { get; set; }
public virtual Editor Editor { get; set; }
}
}
namespace FluentNHibernateSandbox.Entities
{
public class Group : EntityBase
{
public virtual string Name { get; set; }
public virtual string Label { get; set; }
public virtual string Description { get; set; }
public virtual int SortOrder { get; set; }
public virtual IList<Attribute> Attributes { get; set; }
}
}
namespace FluentNHibernateSandbox.Entities
{
public class Editor : EntityBase
{
public virtual string ViewName { get; set; }
public virtual string WorkerClassName { get; set; }
}
}
In general, what I ultimately want doesn't seem like it should be all that hard to do, but I after having tried just about every combination of mappings I can think of, I still can't seem to get it right. I just need my Attribute to have a reference to the Group that it belongs to and a reference to the Editor assigned to it, and each Group should have a collection of the Attributes that are part of it. The couple of many-to-many join tables are what seem to be giving me fits. Particularly the APPLICATION_ATTRIBUTE table. Ultimately I only want the Attributes that my application is concerned with, in this case, those with an APPLICATION_ID of 4.
Any help would be greatly appreciated. Thanks.

Really kinda surprised nobody responded to this at all, but anyway. The answer/solution for this mapping situation that we came up with, which I was trying to avoid to start with, but turned out to really be the best way to go, was to create some custom views in the database that joined together all of the application-specific data I needed, and then just mapped my application's domain objects to those views. This worked at least partially because the information I needed from these tables is going to be read-only for this application, but even if I needed to write to the tables, I'm pretty sure (though haven't verified as I didn't really have need in this case) that I could have setup my views to be writeable and that would've worked too.
Hat tip to #robconery.

Related

Parameter xxx of domain operation entry xxx must be one of the predefined serializable types

I get this webservice error sometimes on a SL5 + EF + WCF app.
"Parameter 'role' of domain operation entry 'AddUserPresentationModelToRole' must be one of the predefined serializable types."
here is a similar error, however his solution doesn't work for me.
I have the codegenned DomainService which surfaces the database entities to my client:
[EnableClientAccess()]
public partial class ClientAppDomainService : LinqToEntitiesDomainService<ClientAppUserEntitlementReviewEntities>
{
public IQueryable<Account> GetAccounts()
{
return this.ObjectContext.Accounts;
}
//..etc...
and my custom service which is surfacing a Presentation model, and db entities.
[EnableClientAccess]
[LinqToEntitiesDomainServiceDescriptionProvider(typeof(ClientAppUserEntitlementReviewEntities))]
public class UserColourService : DomainService
{
[Update(UsingCustomMethod = true)]
public void AddUserPresentationModelToRole(UserPresentationModel userPM, Role role, Reviewer reviewer)
{
...
}
public IDictionary<long, byte> GetColourStatesOfUsers(IEnumerable<RBSUser> listOfUsers, string adLogin)
{
//....
}
}
and the PresentationModel:
public class UserPresentationModel
{
[Key]
public long UserID { get; set; }
public byte UserStatusColour { get; set; }
public string MessageText { get; set; }
[Include]
[Association("asdf", "UserID", "UserID")]
public EntityCollection<Account> Accounts { get; set; }
public DateTime AddedDate { get; set; }
public Nullable<long> CostCentreID { get; set; }
public DateTime? DeletedDate { get; set; }
public string EmailAddress { get; set; }
public long EmployeeID { get; set; }
public string FirstName { get; set; }
public Nullable<bool> IsLeaver { get; set; }
public string LastName { get; set; }
public DateTime LastSeenDate { get; set; }
public string LoginDomain { get; set; }
public string LoginName { get; set; }
public byte WorldBuilderStatusID { get; set; }
}
Also cannot get the solution to reliably fail. It seems whenever I change the service slightly ie make it recompile, everything works.
RIAServices unsupported types on hand-built DomainService - seems to be saying the same thing, that decorating the hand built services with the LinqToEntitiesDomainServiceDescriptionProvider should work.
Possible answer here will post back here too with results.
From Colin Blair:
I am a bit surprised it ever works, I don't think I have seen anyone trying to pass additional entiities into a named update before. It might be a bug in RIA Services that it is working at all. What are you trying to accomplish?
Side note, you have a memory leak with your ObjectContext since it is not getting disposed of correctly. Is there a reason you aren't using the LinqToEntitiesDomainSerivce? It would take care of managing the ObjectContext's lifetime for you.
Results:
1) This makes sense. Have refactored out to more sensible parameters now (ints / strings), and all working.
2) Have brought together my 3 separate services into 1 service, which is using the LinqToEntitiesDomainSerivce. The reason I'd split it out before was the assumption that having a CustomUpdate with a PresentationModel didn't work.. and I had to inherit off DomainService instead. I got around this by making a method:
// need this to avoid compile errors for AddUserPresentationModelToRole.. should never be called
public IQueryable<UserPresentationModel> GetUserPresentationModel()
{
return null;
}

How to map and reference entities from other data sources with NHibernate

I'm currently working on and ASP.NET MVC application in which I have a User entity like follows:
public class User
{
public virtual int Id { get; protected set; }
public virtual string Name { get; protected set; }
public virtual string Role { get; protected set; }
public virtual Location Location { get; protected set; }
}
Where location is just as straightforward:
public class Location
{
public virtual string Id { get; protected set; }
public virtual string Building { get; protected set; }
public virtual string City { get; protected set; }
public virtual string Region { get; protected set; }
}
My complication arises because I want to populate the User from Active Directory and not the database. Additionally, several classes persisted to the database reference a user as a property. I've got an ADUserRepository for retrieval, but I don't know how to integrate these Users into my object graph when the rest is managed by NHibernate.
Is there a way for NHibernate to persist just an id for a User without it being a foreign key to a Users table? Can I map it as a component to accomplish this? I've also looked at implementing IUserType to make the translation. That way it would map to a simple field and ADUserRepository could be put in the chain to resolve the stored Id. Or am I trying to hack something that's not really feasible? This is my first time around with NHibernate so I appreciate any insight or solutions you can give. Thanks.
Update
It appears my best solution on this will be to map the User with an IUserType and inject (preferably with StructureMap) a service for populating the object before its returned. Framed in that light there are a couple of questions here that deal with the topic mostly suggesting the need for a custom ByteCodeProvider. Will I still need to do this in order for IUserType to take a parameterized constructor or do the comments here: NHibernate.ByteCode.LinFu.dll For NHibernate 3.2 make a difference?
using a Usertype to convert user to id and back
public class SomeClass
{
public virtual string Id { get; protected set; }
public virtual User User { get; protected set; }
}
// in FluentMapping (you have to translate if you want to use mapping by code)
public SomeClassMap()
{
Map(x => x.User).Column("user_id").CustomType<UserType>();
}
public class UserType : IUserType
{
void NullSafeSet(...)
{
NHibernateUtil.Int32.NullSafeSet(cmd, ((User)value).Id, index);
}
void NullSafeGet(...)
{
int id = (int)NHibernateUtil.Int32.NullSafeGet(cmd, ((User)value).Id, index);
var userrepository = GetItFromSomeWhere();
return userrepository.FindById(id);
}
}

Fluent Nhibernate Many to Many association to multiple classes

Fluent Nhibernate Many to Many association to multiple classes
We use Nhibernate and up to now we have been able use the auto mapping. But I think this is about to change.
We have a Code class that has a many to many relation with several other classes.
I’m thinking something along these lines:
public class Code
{
public virtual Guid Id { get; set; }
public virtual ICollection<CodeUsage> Usage { get; set; }
}
class CodeUsage
{
public virtual Guid Id { get; set; }
public virtual Code Code { get; set; }
// Class, [Property,] Id for "ANY" mapping to A & B
}
class A
{
public virtual Guid Id { get; set; }
public virtual ICollection<CodeUsage> Codes { get; set; }
}
class B
{
public virtual Guid Id { get; set; }
public virtual ICollection<CodeUsage> Codes { get; set; }
}
Many to Many will lead to the creation of a linking table, in the linking table their needs come a mapping to the classes using codes. In the documentation it is referred to as a “Any” mapping.
But I have no idea how get fluent to create one.
Thoughts anyone? or even better: a solution <);o)}{
You can't map <many-to-any> in Fluent NHibernate - it's not supported.
I think it may be a good reason to move to mapping-by-code, that supports it well.

DbDataController in MVC4 UpdateEntity failing

I have a datamodel like
ModelA which contains a Collection.
ModelB contains a Collection as a backreference. That is failing because of cyclic references if I query with Include("ModelB"). Not good but I solved that via setting ModelB.List=null for each element.
The problem now is submitting a changed ModelA tree: I am adding ModelB-entities to ModelA.ModelB[]. Now the UpdateEntity function is complaining the it could not add elements of type ModelB which are declared static. The JSON deserializer is creating static arrays.
How is it possible with the combination of upshot/MVC4 to submit datamodels which are not completely flat? As it is not possible right now to create your own DTO objects where you might figure out something I am stuck now...
After investigating the error a bit better, I think the problem is the cyclic backreference:
The ModelA->ModelB->ModelA is breaking the storage of the data. "Could not add data of type ModelA to type ModelB".
As I mentioned the backreference was set to Null because the cyclic ref serialisation problem...
I hope the will be some easier way on doing more manually with DTO objects where I have mroe control.
Please see also: MVC 4, Upshot entities cyclic references for the beginning of the journey...
To solve the cyclic backreference, you can use the ignoreDataMember attribute:
public class Customer
{
[Key]
public int CustomerId { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public virtual ICollection<Delivery> Deliveries { get; set; }
}
public class Delivery
{
[Key]
public int DeliveryId { get; set; }
public string Description { get; set; }
public bool IsDelivered { get; set; }
[IgnoreDataMember]
public virtual Customer Customer { get; set; }
public virtual int CustomerId { get; set; }
}
I posted a working solution to your problem in a different question: https://stackoverflow.com/a/10010695/1226140

Automapper and NHibernate lazy loading

I am struggling with this issue:
I have a list of NHibernate objects called "Project". These objects contain a lazy - loaded list of "Branches". I am trying to pass a list of Projects to a WCF service so I am using AutoMapper to transform them to flat objects.
The problem is that even though the destination objects called "ProjectContract" does not contain a list of Branches, Automapper still invokes this collection and a lot of queries are made to the database because NHibernate fires the lazy - loading and loads the Branches collection for each project.
Here are the classes and the mapping:
public class Project
{
public virtual int ID
{
get;
set;
}
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual IList<Branch> Branches { get; set; }
}
[DataContract]
public class ProjectContract
{
[DataMember]
public virtual int ID
{
get;
set;
}
[DataMember]
public virtual string Name { get; set; }
[DataMember]
public virtual string Description { get; set; }
}
public class ProjectMappings : Profile
{
protected override void Configure()
{
Mapper.CreateMap<Project, ProjectContract>();
}
}
My question is: Is there a way to tell AutoMapper to not touch the "Branches" collection because I don't care about it and that is a proxy that will trigger many database calls?
I temporarily fixed this with MaxDepth(0), but there are other entities where I have collections that I want to transfer, and collections that I don't want to be touched, like this one. In that case, MaxDepth(0) will not work.
Thank you,
Cosmin
Yes, The AutoMapper Ignore function.
Mapper.CreateMap<Source, Destination>()
.ForMember(dest => dest.SomeValuefff, opt => opt.Ignore());