I'm using Table Per Type(TPT) to do inheritance in Nhibernate v3.3.1.4000. I figured out that any SQL for SubClass relationships one-to-many are wrong.
Class:
public class Repasse : Colaboracao
{
public virtual string Descricao { get; set; }
public virtual Decimal ValorRepasse { get; set; }
public virtual DateTime DataInicio { get; set; }
public virtual DateTime DataTermino { get; set; }
[XmlIgnore]
public virtual Usuario UsuarioExecucao { get; set; }
[XmlIgnore]
public virtual Usuario UsuarioMonitoramento { get; set; }
[XmlIgnore]
public virtual IList<RepasseRecebido> RepassesRecebidos { get; set; }
[XmlIgnore]
public virtual IList<RepasseProduto> Produtos { get; set; }
public Repasse()
{
RepassesRecebidos = new List<RepasseRecebido>();
Produtos = new List<RepasseProduto>();
UsuarioExecucao = new Usuario();
UsuarioMonitoramento = new Usuario();
}
}
public class RepasseRecebido : Entidade
{
public virtual string NumNotaAtorizacao { get; set; }
public virtual Decimal ValorTaxaCambio { get; set; }
public virtual DateTime DataRecebimento { get; set; }
public virtual Decimal ValorRecebido { get; set; }
public virtual string Observacao { get; set; }
[XmlIgnore]
public virtual Repasse Repasse { get; set; }
[XmlIgnore]
public virtual List<Download> Downloads { get; set; }
public RepasseRecebido()
{
Repasse = new Repasse();
Downloads = new List<Download>();
}
}
public class RepasseProduto : Entidade
{
public virtual int QtdProduto { get; set; }
public virtual DateTime DataInicio { get; set; }
public virtual DateTime DataTermino { get; set; }
public virtual int QtdBeneficiado { get; set; }
public virtual PublicoBeneficiado PublicoBeneficiado { get; set; }
[XmlIgnore]
public virtual Produto Produto { get; set; }
[XmlIgnore]
public virtual Repasse Repasse { get; set; }
[XmlIgnore]
public virtual IList<RepasseProdutoAtividade> Atividades { get; set; }
public RepasseProduto()
{
Produto = new Produto();
Repasse = new Repasse();
Atividades = new List<RepasseProdutoAtividade>();
}
}
public class RepasseProdutoAtividade : Entidade
{
public virtual DateTime DataInicio { get; set; }
public virtual DateTime DataTermino { get; set; }
public virtual string Descricao { get; set; }
[XmlIgnore]
public virtual RepasseProduto RepasseProduto { get; set; }
public RepasseProdutoAtividade()
{
RepasseProduto = new RepasseProduto();
}
}
Map:
public class RepasseMap : SubclassMap<Repasse>
{
public RepasseMap()
{
Schema(ConfigInstances.ObterSchema("Sigma"));
Table("tblRepasse");
LazyLoad();
KeyColumn("cmpIdRepasse");
Map(x => x.Descricao).Column("cmpDcDescricao");
Map(x => x.ValorRepasse).Column("cmpVlValorRepasse").Not.Nullable();
Map(x => x.DataInicio).Column("cmpDtDataInicio").Not.Nullable();
Map(x => x.DataTermino).Column("cmpDtDataTermino").Not.Nullable();
References(x => x.UsuarioExecucao).Column("cmpIdUsuarioExecucao");
References(x => x.UsuarioMonitoramento).Column("cmpIdUsuarioMonitoramento");
HasMany(x => x.RepassesRecebidos).AsBag().LazyLoad();
HasMany(x => x.Produtos).KeyColumn("cmpIdRepasseProduto").AsBag().LazyLoad();
}
public class RepasseRecebidoMap : ClassMap<RepasseRecebido>
{
public RepasseRecebidoMap()
{
Schema(ConfigInstances.ObterSchema("Sigma"));
Table("tblRecursoRepasse");
LazyLoad();
Id(x => x.Id).GeneratedBy.Identity().Column("cmpIdRecursoRepasse");
Map(x => x.NumNotaAtorizacao).Column("cmpNuAutorizacaoNota").Not.Nullable();
Map(x => x.DataRecebimento).Column("cmpDtDataRecebimento").Not.Nullable();
Map(x => x.ValorRecebido).Column("cmpVlValorRecebido").Not.Nullable();
Map(x => x.ValorTaxaCambio).Column("cmpVlTaxaCambio").Not.Nullable();
Map(x => x.Observacao).Column("cmpDcObservacao");
References(x => x.Repasse).Column("cmpIdRepasse");
HasManyToMany(x => x.Downloads)
.Table("tblRecursoRepasseDownload")
.ParentKeyColumn("cmpIdRecursoRepasse")
.ChildKeyColumn("cmpIdDownload")
.AsBag().LazyLoad().Cascade.SaveUpdate();
}
}
public class RepasseProdutoMap : ClassMap<RepasseProduto>
{
public RepasseProdutoMap()
{
Schema(ConfigInstances.ObterSchema("Sigma"));
Table("tblRepasseProduto");
LazyLoad();
Id(x => x.Id).GeneratedBy.Identity().Column("cmpIdRepasseProduto");
Map(x => x.DataInicio).Column("cmpDtDatainicio").Not.Nullable();
Map(x => x.DataTermino).Column("cmpDtDatatermino").Not.Nullable();
Map(x => x.QtdProduto).Column("cmpInQuantidadeproduto").Not.Nullable();
Map(x => x.QtdBeneficiado).Column("cmpIdQuantidadeBeneficiado").Not.Nullable();
Map(x => x.PublicoBeneficiado).Column("cmpIdPublicoBeneficiado").CustomType(typeof(PublicoBeneficiado));
References(x => x.Produto).Column("cmpIdProduto");
References(x => x.Repasse).Column("cmpIdRepasse");
HasMany(x => x.Atividades).AsBag().LazyLoad();
}
}
public class RepasseProdutoAtividadeMap : ClassMap<RepasseProdutoAtividade>
{
public RepasseProdutoAtividadeMap()
{
Schema(ConfigInstances.ObterSchema("Sigma"));
Table("tblRepasseProdutoAtividade");
LazyLoad();
Id(x => x.Id).GeneratedBy.Identity().Column("cmpIdRepasseProdutoAtividade");
Map(x => x.DataInicio).Column("cmpDtInicio").Not.Nullable();
Map(x => x.DataTermino).Column("cmpDtTermino").Not.Nullable();
Map(x => x.Descricao).Column("cmpDcAtividade").Not.Nullable();
References(x => x.RepasseProduto).Column("cmpIdRepasseProduto");
}
}
}
When I query RepasseProduto then SQL is generated with an issue, the query doesn't findout how to get the Foreign Key name for the one-to-many relationship, as you can see below:
select repasse0_.cmpIdRepasse as cmpIdCol1_5_
repasse0_1_.cmpDtDataCriacao as cmpDtDat2_5_
repasse0_1_.cmpStSituacao as cmpStSit3_5_
repasse0_1_.cmpDcCancelamento as cmpDcCan4_5_
repasse0_1_.cmpIdRecurso as cmpIdRec5_5_
repasse0_.cmpDcDescricao as cmpDcDes2_7_
repasse0_.cmpVlValorRepasse as cmpVlVal3_7_
repasse0_.cmpDtDataInicio as cmpDtDat4_7_
repasse0_.cmpDtDataTermino as cmpDtDat5_7_
repasse0_.cmpIdUsuarioExecucao as cmpIdUsu6_7_
repasse0_.cmpIdUsuarioMonitoramento as cmpIdUsu7_7_
from mre_sigma_dsv.dbo.tblRepasse repasse0_
inner join mre_sigma_dsv.dbo.tblColaboracao repasse0_1_
on repasse0_.cmpIdRepasse=repasse0_1_.cmpIdColaboracao
where (select cast(count(*) as INT)
from mre_sigma_dsv.dbo.tblRepasseProduto produtos1_
where repasse0_.cmpIdRepasse=produtos1_.Repasse_id)>#p0
As you can see the last inner select doesn't find out the name of the foreign key from tblRepasseProduto to tblRepasse, then uses Repasse_id that doesn't represent a valid table field.
What should I do? Am I missing something when mapping my sub-class relation?
Really not sure from where the ghost column comes, but there is other issue in the mapping above. In relations one-to-many vs many-to-one, i.e. in fluent HasMany vs References, there must be/is exactly one column representing that. So we need to use the same (one) column for that and should change the mapping this way.
The RepasseMap : SubclassMap<Repasse>:
public RepasseMap()
{ ...
// was:
// HasMany(x => x.RepassesRecebidos).AsBag().LazyLoad();
// HasMany(x => x.Produtos).KeyColumn("cmpIdRepasseProduto").AsBag().LazyLoad();
// should be
HasMany(x => x.RepassesRecebidos)
.KeyColumn("cmpIdRepasse").AsBag().LazyLoad();
HasMany(x => x.Produtos)
.KeyColumn("cmpIdRepasse").AsBag().LazyLoad();
}
The RepasseRecebidoMap : ClassMap<RepasseRecebido>:
public RepasseRecebidoMap()
{ ...
// the same column representing this relationship in table "tblRecursoRepasse"
References(x => x.Repasse).Column("cmpIdRepasse");
The RepasseProdutoMap : ClassMap<RepasseProduto>:
public RepasseProdutoMap()
{ ...
// the same column representing this relationship in table "tblRepasseProduto"
References(x => x.Repasse).Column("cmpIdRepasse");
If this does not help, could you please send the query you've used and which generated that strange relationship.
Also, in the Mapping snippet above you are nesting the mapping classes ... this is not the right/required way.
i have two class
public class ProInfo
{
public ProInfo()
{
ProPrices = new List<ProPrice>();
}
public virtual Guid ProID { get; set; }
public virtual string ProCate { get; set; }
public virtual string Name { get; set; }
public virtual string Unit { get; set; }
public virtual string PicName { get; set; }
public virtual string Memo { get; set; }
public virtual bool DeleteFlag { get; set; }
public virtual DateTime LastUpDateTime { get; set; }
public virtual IList<ProPrice> ProPrices { get; set; }
}
public class ProPrice
{
public virtual int Id { get; set; }
public virtual AreaInfo AreaInfo { get; set; }
public virtual ProInfo ProInfo { get; set; }
public virtual Decimal Price { get; set; }
}
mapping codes are :
public ProInfoMap()
{
Id(x => x.ProID);
Map(x => x.DeleteFlag);
Map(x => x.Name);
Map(x => x.PicName);
Map(x => x.ProCate);
Map(x => x.Unit);
Map(x => x.LastUpDateTime);
HasMany<ProPrice>(x => x.ProPrices);
}
public ProPriceMap()
{
Id(x => x.Id);
Map(x => x.Price);
References<ProInfo> (x => x.ProInfo);
References<AreaInfo>(x => x.AreaInfo);
}
what i want is to disable the proprices's lazyload(), so i can get all the prices for the product from database. but, when i change the onetomany to this: HasMany<ProPrice>(x => x.ProPrices).Not.LazyLoad(), it cause an Infinite loop. what do i miss?
I don't know, where exactly the loop comes from, but your bidirectional association may cause this. You should declare one side as Inverse(). This can only be done in ProInfoMap, because it is a one-to-many relationship with a bidirectional association:
HasMany<ProPrice>(x => x.ProPrices).Inverse().Not.LazyLoad();
Try that. It may remove the infinite loop.
Hi I have an object called document and one called user
Document
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual User User { get; set; }
Documentmap
public DocumentMap()
{
Map(x => x.Name);
Map(x => x.Description);
References(x => x.User);
}
User
public virtual string UserId { get; set; }
public virtual string FirstName { get; set; }
public virtual string MiddleInitial { get; set; }
public virtual string LastName { get; set; }
private readonly IList<Document> _documents = new List<Document>();
public virtual IEnumerable<Document> Documents { get { return _documents; } }
public virtual void Remove(Document document)
{
_documents.Remove(document);
}
public virtual void Add(Document document)
{
if (!document.IsNew() && _documents.Contains(document)) return;
_documents.Add(document);
}
Map(x => x.UserId);
Map(x => x.FirstName);
Map(x => x.MiddleInitial);
Map(x => x.LastName);
HasMany(x => x.Documents).Access.CamelCaseField(Prefix.Underscore);
Pretty straighforward ( they inherit from base class with stuff like createddate modifieddate etc )
when I try to get all doc by userid I get this
Invalid column name 'UserId'.
the column most definitely is in the table. It also lists several of the base class items as not being there.
I take the sql and past it in query manager and I get intellisense saying they are invalid columns. I run it and it executes just fine. Further more there are plenty of other objects using these base classes with no problems.
I have tried various things like explicitly mapping the key name, the column name using inverse etc to no avail. Don't really know what to do.
Thanks,
Raif
//EDIT as per request sorry it's so verbose. the database is created by nhibernate create schema
Document
public class Document : Entity
{
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual DocumentCategory DocumentCategory { get; set; }
[ValueOf(typeof(DocumentFileType))]
public virtual string FileType { get; set; }
public virtual string FileUrl { get; set; }
public virtual int? Pages { get; set; }
public virtual decimal? Size { get; set; }
public virtual User User { get; set; }
}
public class DocumentMap : EntityMap<Document>
{
public DocumentMap()
{
Map(x => x.Name);
Map(x => x.Description);
Map(x => x.FileUrl);
Map(x => x.Pages);
Map(x => x.Size);
Map(x => x.FileType);
References(x => x.DocumentCategory);
References(x => x.User);
}
}
Entity
public class Entity : IGridEnabledClass, IEquatable<Entity>
{
public virtual int EntityId { get; set; }
public virtual DateTime? CreateDate { get; set; }
public virtual DateTime? ChangeDate { get; set; }
public virtual int ChangedBy { get; set; }
public virtual bool Archived { get; set; }
public virtual bool IsNew()
{
return EntityId == 0;
}
User
public class User : DomainEntity, IUser
{
public virtual string UserId { get; set; }
[ValidateNonEmpty]
public virtual string FirstName { get; set; }
public virtual string MiddleInitial { get; set; }
[ValidateNonEmpty]
public virtual string LastName { get; set; }
public virtual string Title { get; set; }
public virtual DateTime? BirthDate { get; set; }
public virtual string StartPage { get; set; }
public virtual UserLoginInfo UserLoginInfo { get; set; }
public virtual UserStatus UserStatus { get; set; }
public virtual Photo HeadShot { get; set; }
private readonly IList<Document> _documents = new List<Document>();
public virtual IEnumerable<Document> Documents { get { return _documents; } }
public virtual void Remove(Document document)
{
_documents.Remove(document);
}
public virtual void Add(Document document)
{
if (!document.IsNew() && _documents.Contains(document)) return;
_documents.Add(document);
}
several more collections
public class UserMap : DomainEntityMap<User>
{
public UserMap()
{
Map(x => x.UserId);
Map(x => x.FirstName);
Map(x => x.MiddleInitial);
Map(x => x.LastName);
Map(x => x.BirthDate);
Map(x => x.StartPage);
References(x => x.UserStatus);
References(x => x.UserLoginInfo);
References(x => x.HeadShot);
HasMany(x => x.Documents).Access.CamelCaseField(Prefix.Underscore);
database tables create from script select to menu item on management studio
SELECT [EntityId]
,[CreateDate]
,[ChangeDate]
,[ChangedBy]
,[Archived]
,[Name]
,[Description]
,[FileUrl]
,[Pages]
,[Size]
,[FileType]
,[DocumentCategoryId]
,[UserId]
FROM [DecisionCriticalSuite].[dbo].[Document]
GO
SELECT [EntityId]
,[CreateDate]
,[ChangeDate]
,[ChangedBy]
,[Archived]
,[TenantId]
,[OrgId]
,[UserId]
,[FirstName]
,[MiddleInitial]
,[LastName]
,[BirthDate]
,[StartPage]
,[UserStatusId]
,[UserLoginInfoId]
,[HeadShotId]
,[OrganizationId]
FROM [DecisionCriticalSuite].[dbo].[User]
GO
error from nhprof
ERROR:
Invalid column name 'UserId'.
Invalid column name 'UserId'.
Invalid column name 'EntityId'.
Invalid column name 'EntityId'.
Invalid column name 'CreateDate'.
Invalid column name 'ChangeDate'.
Invalid column name 'ChangedBy'.
Invalid column name 'Archived'.
Invalid column name 'FileType'.
Invalid column name 'UserId'.Could not execute query: SELECT documents0_.UserId as UserId1_, documents0_.EntityId as EntityId1_, documents0_.EntityId as EntityId49_0_, documents0_.CreateDate as CreateDate49_0_, documents0_.ChangeDate as ChangeDate49_0_, documents0_.ChangedBy as ChangedBy49_0_, documents0_.Archived as Archived49_0_, documents0_.Name as Name49_0_, documents0_.Description as Descript7_49_0_, documents0_.FileUrl as FileUrl49_0_, documents0_.Pages as Pages49_0_, documents0_.Size as Size49_0_, documents0_.FileType as FileType49_0_, documents0_.DocumentCategoryId as Documen12_49_0_, documents0_.UserId as UserId49_0_ FROM [Document] documents0_ WHERE documents0_.UserId=#p0
Make sure nhibernate is querying against the same database as what you are querying against in sql management studio.
I just had the same issue because I had mapped Entity1.Entity2 as Entity3.
So when joining, it would attempt to use a property from Entity3 as if it existed on Entity2.
i want to create something like
SELECT * FROM dbo.localconveyance_details WHERE
voucherNo IN (SELECT voucherNo FROM dbo.localconveyance_master WHERE emp_code = '48'
using linq in fluent nhibernate
tried something like this
IList<LocalConveyanceDetails> detailslist = session.Query<LocalConveyanceDetails>()
.Where(x => x.LocalConveyanceMaster.emp_code == e_id).ToList();
but its not working ... can someone tell what would be the actual query ?
Update :
the Entities which i have used are :
public class LocalConveyanceMaster
{
public virtual String voucherNo { get; set; }
public virtual DateTime voucher_date { get; set; }
public virtual String emp_code { get; set; }
public virtual String emp_name { get; set; }
public virtual String project_id { get; set; }
public virtual DateTime submitDate { get; set; }
public virtual String to_be_approved_by { get; set; }
public virtual String created_by { get; set; }
public virtual Decimal conveyance_total { get; set; }
public virtual Decimal approved_amount { get; set; }
public virtual String approved { get; set; }
public virtual ProjectMaster Project { get; set; }
public virtual ICollection<LocalConveyanceDetails> LocalConveyanceDetails { get; set; }
}
public class LocalConveyanceDetails
{
public virtual String LcDetailsId { get; set; }
public virtual String voucherNo { get; set; }
public virtual String serialNo { get; set; }
public virtual String From_Project_Id { get; set; }
public virtual String To_Project_Id { get; set; }
public virtual DateTime particularsDate { get; set; }
public virtual Decimal particularsAmount { get; set; }
public virtual String particulars { get; set; }
public virtual LocalConveyanceMaster LocalConveyanceMaster { get; set; }
}
and the mappings are :
public LocalConveyanceMap()
{
Table("localconveyance_master");
Id(x => x.voucherNo).Column("voucherNo");
Map(x => x.voucher_date);
Map(x => x.emp_code);
Map(x => x.emp_name);
Map(x => x.project_id);
Map(x => x.submitDate);
Map(x => x.to_be_approved_by);
Map(x => x.created_by);
Map(x => x.conveyance_total);
Map(x => x.approved_amount);
Map(x => x.approved);
References(x => x.Project)
.Column("project_id")
.ForeignKey("project_id");
HasMany(x => x.LocalConveyanceDetails)
.KeyColumn("voucherno").AsSet();
}
public LocalConveyanceDetailsMap()
{
Table("Localconveyance_details");
Id(x => x.LcDetailsId).Column("LcDetailsId");
Map(x => x.voucherNo);
Map(x => x.serialNo);
Map(x => x.From_Project_Id);
Map(x => x.To_Project_Id);
Map(x => x.particularsDate);
Map(x => x.particularsAmount);
Map(x => x.particulars);
References(x => x.LocalConveyanceMaster)
.PropertyRef(x => x.voucherNo).Column("voucherno")
.ForeignKey("voucherno");
}
the error which i am getting is :
Exception : {"Error performing LoadByUniqueKey[SQL: SQL not available]"}
InnerException : {"The given key was not present in the dictionary."}
that's occurred when the one or more member of class is kind of other class [relationship].
i have a same problem and i remove that members and add new member for each of them in this form :
public virtual int? [related class]id {get;set;}
exmaple :
public virtual int? PersonId {get;set;}
I am getting the following error using Fluent:
12:16:47,879 ERROR [ 7]
Configuration [(null)]- An association
from the table Address refers to an
unmapped class: System.Int32
NHibernate.MappingException: An
association from the table Address
refers to an unmapped class:
System.Int32
public class Address {
public Address() {
}
public virtual int AddressId {
get;
set;
}
public virtual string AddressLine1 {
get;
set;
}
public virtual string AddressLine2 {
get;
set;
}
public virtual string AddressLine3 {
get;
set;
}
public virtual string BuildingNumber {
get;
set;
}
public virtual string City {
get;
set;
}
public virtual string County {
get;
set;
}
public virtual System.DateTime MovedIn {
get;
set;
}
public virtual System.DateTime MovedOut {
get;
set;
}
public virtual int PersonId {
get;
set;
}
public virtual string PostCode {
get;
set;
}
}
public class AddressMap : ClassMap<Address> {
public AddressMap() {
Table("Address");
LazyLoad();
Id(x => x.AddressId).GeneratedBy.HiLo("1000");
Map(x => x.AddressLine1).Length(100).Not.Nullable();
Map(x => x.AddressLine2).Length(100).Not.Nullable();
Map(x => x.AddressLine3).Length(100).Not.Nullable();
Map(x => x.BuildingNumber).Length(250).Not.Nullable();
Map(x => x.City).Length(250).Not.Nullable();
Map(x => x.County).Length(250).Not.Nullable();
Map(x => x.MovedIn).Not.Nullable();
Map(x => x.MovedOut).Not.Nullable();
References(x => x.PersonId).Column("PersonId").Not.Nullable();
Map(x => x.PostCode).Length(15).Not.Nullable();
}
}
[TestFixture]
public class TestBase
{
protected SessionSource SessionSource { get; set; }
protected ISession Session { get; private set; }
[SetUp]
public void SetupContext()
{
var cfg = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005.ConnectionString(
"Data Source=localhost;Initial Catalog=ted;User ID=sa;Password=xxxx;"));
SessionSource = new SessionSource(cfg.BuildConfiguration()//**Error Here**
.Properties, new TestModel());
Session = SessionSource.CreateSession();
SessionSource.BuildSchema(Session);
}
[TearDown]
public void TearDownContext()
{
Session.Close();
Session.Dispose();
}
}
I get an error on my initial configuration, I have been over it a few times and I am really unsure what exactly I am doing wrong? Can anyone see anything Obvious? I can confirm there is only 2 int's in the database for this table. AddressId - Non identity PK and PersonId non identity FK
You should have a Person property of type Person, not an id.
Suggested read: https://github.com/jagregory/fluent-nhibernate/wiki/Getting-started