I Have two classes, Survey and Poll classes. Also I have Question and Question Choice classes. How do I map these so I come out with particular table formats. Here are the classes involved.
public class Survey
{
public IList<Question> Questions { get; private set; }
}
public class Poll
{
public Question Question { get; set; }
}
public class Question
{
public string Text { get; set; }
public IList<QuestionChocie> Choices { get; private set; }
}
public class QuestionChoice
{
public string Text { get; set; }
}
The resulting tables that I'm shooting for include the following
Surveys- a table of survey information.
Polls - a table of polls information.
SurveyQuestions -a table of survey questions.
PollQuestions - a table of poll questions.
SurveyChoices - a table of the question choices for the surveys.
PollChoices - a table of the question choices for the survey.
Preferably, I really want to know for Fluent NHibernate, or just mapping xml is fine too.
You haven't defined relationships between the tables so I'm going to assume one-to-many.
The general mapping would be:
public class SurveyMap : ClassMap<Survey>
{
public SurveyMap()
{
HasMany<SurveyQuestion>(x => x.Questions).Inverse();
// Rest of mapping
}
}
public class SurveyQuestionMap : ClassMap<Question>
{
public QuestionMap()
{
References<Survey>(x => x.Survey);
HasMany<SurveyChoice>(x => x.Choices).Inverse();
// Rest of mapping
}
}
public class SurveyChoiceMap : ClassMap<SurveyChoice>
{
public SurveyChoiceMap()
{
References<SurveyQuestion>(x => x.Question);
// Rest of mapping
}
}
Related
I have two classes:
class User {
public int Id { get;set; }
public string Name { get; set; }
}
class VerifiedUser : User {
public ICollection<Verified> { get; set; }
}
I would like NHibernate to treat VerifiedUser and User as the same table but keep them separate to, so.
Session.Query<User>() //would return a User
Session.Query<VerifiedUser>() //would return a VerifiedUser
Is this possible or is it unsupported?
You will need to implement the table-per-hierarchy strategy with Fluent Nhiberate in mapping classes. These are like overrides for the AutoMapping feature (if used) of FNH, otherwise mapping classes are de facto and you will be used to them.
Something like:
public class UserMappingOverride : IAutoMappingOverride<User>
{
public void Override(AutoMapping<User> mapping)
{
mapping.DiscriminateSubClassesOnColumn("IsVerified").Not.Nullable();
}
}
public class VerifiedUserClassMap : SubclassMap<VerfiedUser>
{
public VerifiedUserClassMap()
{
DiscriminatorValue("Yes");
}
}
And to answer your question, yes as far as I remember nothing to do here: Session.QueryOver<VerifiedUser>() as NHibernate will add on the where clause for the discriminator
I am using MVC3 and Entity Framework. I have a class called User with 20 different properties. I have already created a database and filled it with some data. I want to break out the Addresses property and make it it's own class.
namespace NameSpace.Domain.Entities
{
public class User
{
public int UserId { get; set; }
...
...
public string AddressOne { get; set; }
public string AddressTwo { get; set; }
}
}
I want to break out both Addresses like so
namespace NameSpace.Domain.Entities
{
public class User
{
public int UserId { get; set; }
...
...
public Addresses Addresses { get; set; }
}
public class Addresses
{
public string AddressOne { get; set; }
public string AddressTwo { get; set; }
}
}
HERE'S MY QUESTION:
Since I already have the data table filled with data, how can I update this in the Server Explorer?
Thanks ( if you need more info please let me know )
If you are using EF code first 4.3 you can use the concept of migrations to achive what you want.
You will need to do a code based manual migration since you change is a bit to advanced for the framework to figure it out itselfe.
Further reading: http://blogs.msdn.com/b/adonet/archive/2012/02/09/ef-4-3-code-based-migrations-walkthrough.aspx
I have the following database tables defined:
Club: Id, Name
Member: Id, Name
ClubMember: ClubId, MemberId
I have the following entity Classes defined:
public class Club() {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Member> Members { get; set; }
}
public class Member() {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Club> Clubs { get; set; }
}
I have the following overrides defined:
public class MemberOverride : IAutoMappingOverride<Member>
{
public void Override(AutoMapping<Member> mapping_)
{
mapping_
.HasManyToMany(x_ => x_.Clubs)
.ParentKeyColumn("MemberId")
.ChildKeyColumn("ClubId")
.Cascade.All()
.Table("ClubMembers");
}
}
public class ClubOverride : IAutoMappingOverride<Club>
{
public void Override(AutoMapping<Club> mapping_)
{
mapping_
.HasManyToMany(x_ => x_.Members)
.ParentKeyColumn("ClubId")
.ChildKeyColumn("MemberId")
.Inverse()
.Table("ClubMembers");
}
}
I can see from my overrides that the Inverse on the ClubOverride means you cannot do the following
session.Save(club.Members.Add(member));
but this works:
session.Save(member.Clubs.Add(club);
But it doesn't make logical sense. I want to be able to save either the club with members or member with clubs.
Am I trying to do something impossible with FluentNhibernate?
TIA
Yes, you're right, that's not possible. But it's not a question of FluentNhibernate, NHibernate works like that.
Only one side is the owner of the relation and on charge of adding elements.
From official documentation:
Changes made only to the inverse end of the association are not persisted. This means that NHibernate has two representations in memory for every bidirectional association, one link from A to B and another link from B to A. This is easier to understand if you think about the .NET object model and how we create a many-to-many relationship in C#:
You can create add or remove methods on your entities that will help accomplish this:
public class Club() {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
private IList<Member> members;
public virtual IEnumerable<Member> Members { get { return members.Select(x => x); } }
public Club() {
members = new List<Member>();
}
public virtual void AddMember(Member member){
if (members.Contains(member))
return;
members.Add(user);
member.AddClub(this);
}
public virtual void RemoveMember(Member member){
if (!members.Contains(member))
return;
members.Remove(member);
member.RemoveClub(this);
}
}
I am having trouble using CreateCriteria to add an outer join to a criteria query while using Fluent NHibernate with automapping.
Here are my entities -
public class Table1 : Entity
{
virtual public int tb1_id { get; set; }
virtual public DateTime tb1_date_filed { get; set; }
.
.
.
virtual public IList<Table2> table2 { get; set; }
}
public class Table2: Entity
{
public virtual int tb2_id { get; set; }
public virtual int tb2_seqno { get; set; }
.
.
.
public virtual Table2 table2 { get; set; }
}
I try to use the following to add an outer join to my criteria query -
CreateCriteria("Table2", NHibernate.SqlCommand.JoinType.LeftOuterJoin);
But I am getting an error -
{"EIX000: (-217) Column (tbl1_id) not found in any table in the query (or SLV is undefined)."}
So it seems that it is trying to automatically set the id of the second table, but doesn't know what to set it to. Is there a way that I can specifically set the id? Here is my Session -
var persistenceModel = AutoMap.AssemblyOf<Table1>()
.Override<Table1>(c => {
c.Table("case");
c.Id(x => x.id).Column("tbl1_id");
})
.Where(t => t.Namespace == "MyProject.Data.Entities")
.IgnoreBase<Entity>();
Hope that makes some sense. Thanks for any thoughts.
You seem to have answered your own question so I'm just going to spout some recommendations...
One of the nice things about fluent nhibernate is that it follows conventions to automatically create mappings. Your entities seem to be very coupled to the names of your database tables.
In order to map to a different database convention while keeping idealistic names for entities and columns you can use some custom conventions:
public class CrazyLongBeardedDBATableNamingConvention
: IClassConvention
{
public void Apply(IClassInstance instance)
{
instance.Table("tbl_" + instance.EntityType.Name.ToLower());
}
}
public class CrazyLongBeardedDBAPrimaryKeyNamingConvention
: IIdConvention
{
public void Apply(IIdentityInstance instance)
{
string tableShort = TableNameAbbreviator.Abbreviate(instance.EntityType.Name);
instance.Column(tableShort + "_id");
}
}
class CrazyLongBeardedDBAColumnNamingConvention : IPropertyConvention
{
public void Apply(IPropertyInstance instance)
{
string name = Regex.Replace(
instance.Name,
"([A-Z])",
"_$1").ToLower();
var tableShort = TableNameAbbreviator.Abbreviate(instance.EntityType.Name);
instance.Column(tableShort + name);
}
}
TableNameAbbreviator is a class that would know how to abbreviate your table names.
These would map from:
public class Table1 : Entity
{
virtual public int Id { get; set; }
virtual public DateTime DateFiled { get; set; }
}
To a table like:
CREATE TABLE tbl_table1 {
tbl1_id INT PRIMARY KEY
tbl1_date_filed datetime
}
I added a HasMany option to the override for my first table to define the relationship to my second table. I then added an override for my second table which defines the id column for that table.
Thank
While playing around with one-to-one associations in castle activerecord I stumbled upon the following problem:
I'm trying to model a one-to-one relationship (user-userprofile in this case). I already learned that this may not be a best practice, but let's ignore that for a moment (I'm still trying to understand what's going on).
[ActiveRecord]
public class TestUser : ActiveRecordBase<TestUser>
{
[PrimaryKey(PrimaryKeyType.GuidComb)]
public Guid Id { get; set; }
}
[ActiveRecord]
public class TestUserProfile : ActiveRecordBase<TestUserProfile>
{
[PrimaryKey(PrimaryKeyType.GuidComb)]
public Guid Id { get; set; }
[OneToOne(Cascade = CascadeEnum.All, Fetch = FetchEnum.Join)]
public TestUser User { get; set; }
}
I would expect the following code to save a user with profile, yielding the same Id in the database:
[Test]
public void save_profile_saves_user()
{
var profile = new TestUserProfile
{
User = new TestUser()
};
profile.Save();
}
The actual result however is that both objects are saved with a different key. Am I missing something??
I've found the answer myself. The PrimaryKeyType of the side of the relation where OneToOne is defined should have a PrimaryKey of PrimaryKeyType.Foreign:
[ActiveRecord]
public class TestUserProfile : ActiveRecordBase<TestUserProfile>
{
[PrimaryKey(PrimaryKeyType.Foreign)]
public Guid Id { get; set; }
[OneToOne(Cascade = CascadeEnum.All, Fetch = FetchEnum.Join)]
public TestUser User { get; set; }
}
Back to reading the docs more thoroughly...