Fluent NHibernate - Mapping error, XML Validation, Invalid/Incomplete configuration - fluent-nhibernate

I'm fairly new to NH and FNH. I want to map a List of longs, and I'm getting the error:
An invalid or incomplete configuration was used while creating a SessionFactory.
Double inner Exception:
{"(XmlDocument)(15,8): XML validation error: The element 'list' in namespace 'urn:nhibernate-mapping-2.2' has invalid child element 'one-to-many' in Namespace 'urn:nhibernate-mapping-2.2'. List of possible elements expected: 'loader, sql-insert, sql-update, sql-delete, sql-delete-all, filter' in Namespace 'urn:nhibernate-mapping-2.2'."}
My entity:
public class XPTable
{
public virtual int I3D { get; set; }
public virtual IList<long> XPRequired { get; set; }
public XPTable()
{
XPRequired = new List<long>();
}
}
My Mapping:
public class XPTableMaps : ClassMap<XPTable>
{
public XPTableMaps()
{
Table("XPTable");
Id(id => id.I3D);
//this line causes the error
HasMany<long>(many => many.XPRequired).AsList().Element("XPRequired");
}
}
I use NHibernate 3.1.0, FNH 1.0
It's definitely the HasMany mapping that's causing the problem, because when I comment it out, the program runs just fine. The I3D column in the SQL 2008 table is the identity, the names/types of the table and the columns match the mapping. If I leave out the .AsList(), then the error message stays the same except that it refers to 'bag' instead of 'list'. Adding Inverse() and/or Cascade.Whatever() has no effect either.
Any ideas please?

Related

NHibernate fluent mapping - specify tables at runtime?

Question:
How can I pass a string representing a table name to an NHibernate ClassMap?
Details:
I have several databases which are almost the same, with some minor variations in table and view names. I would like to be able to handle these variations via configuration parameters in my app.config file. For example, I could specify the table names for a particular configuration using the following custom section:
<tableNames>
<add key="logicalTable1" value="ACTUAL_TABLE_1"/>
<add key="logicalTable2" value="ACTUAL_TABLE_2"/>
</tablenames>
Now, if I load these config parameters at runtime, how do I get the table name into the ClassMap (i.e.,
public class MyClassMap : ClassMap<MyClass>
{
public class MyClassMap()
{
Table("ACTUAL_TABLE_1"); // <--- HERE I WANT Table(logicaTable1)
...
}
Note: I am using Ninject to inject ISessionFactory -- not sure if this matters.
Unless I am missing something, you could just use the ConfigurationManager class:
public class MyClassMap()
{
var table = ConfigurationManager.AppSettings["logicalTable2"];
Table(table);
...
}
Your project would need to reference the System.Configuration assembly.
Update:
Or use a "TableNameProvider" class:
public interface ITableNameProvider
{
string LogicalTable1 { get; }
}
public class TableNameProvider : ITableNameProvider
{
public string LogicalTable1 { get { return ConfigurationManager.AppSettings["logicalTable1"]; } }
}
I'm not sure about exactly how to do this with Ninject, but assuming its like other containers:
public class MyClassMap()
{
var provider = GetMyContainer().GetInstance<ITableProvider>();
var table = provider.LogicalTable1;
Table(table);
...
}
This way you would just need to change your TableNameProvider class.
I'm not sure if you could inject a MappingFactory or something into Fluent-NHibernate to handle mapping file dependencies and true injection. Something to look into.

Odd error building FluentNH configuration

I have a Fluent NHibernate project I'm working on, and doing some testing I have run into a very strange error:
The entity '<>c__DisplayClass3' doesn't have an Id mapped. Use the Id method to map your identity property. For example: Id(x => x.Id).
The related entity reported is:
{Name = "<>c__DisplayClass3" FullName = "TPLLCPortal.Domain.Account+<>c__DisplayClass3"}
I don't have any class named DisplayClass, but I do have an Account entity. I'm using a primary key convention that looks like this:
public class PrimaryKeyConvention : IIdConvention
{
public void Apply(IIdentityInstance instance)
{
instance.GeneratedBy.GuidComb();
}
}
My Account class inherits from an EntityBase class that declares the ID as:
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
public virtual Guid Id { get; protected internal set; }
I'm confident that I'm setting up the configuration properly and that the conventions are being picked up, but just in case I added an override and specifically mapped the ID for the Account class. No dice.
Any ideas what's going on here?
I'm using FNH 1.3.0.733 with NHibernate 3.3.1.4000 (both loaded off NuGet).
Looks like I figured it out. This SO answer had the key. Because some of the methods on the class use lambdas, the compiler creates classes that you can exclude in the DefaultAutomappingConfiguration by specifying !type.IsDefined(typeof(CompilerGeneratedAttribute), false) as part of the ShouldMap override.

WCF, Linq Error:cannot implicitly convert type System.linq.iorderedQueryable<> to System.Collection.Generic.List<>

I am getting an error : i am using entity framework, wcf.
Error:cannot implicitly convert type System.linq.iorderedQueryable<xDataModel.Info> to System.Collection.Generic.List<xServiceLibrary.Info>
Below are my code:
WCF Service:
namespace xServiceLibrary
{
public List<Info> GetScenario()
{
xEntities db = new xEntities();
var query = from qinfo in db.Infoes
select qinfo;
//return query.Cast<Info>().ToList(); (not working)
//return query.toList(); (not working)
return query;
}
}
Interface:
namespace xServiceLibrary
{
[OperationContract]
List<Info> GetScenario();
}
Class:
namespace xServiceLibrary
{
[DataContract]
public class Info
{
[DataMember]
public int Scenario_Id;
[DataMember]
public string Scenario_Name { get; set; }
[DataMember]
public string Company_Name { get; set; }
}
}
update:(2)
I have two class library files.
One is xDataModel namespace in which i have created xmodel.edmx file.
second is xServiceLibrary namespace where i am implementing Wcf Service.
i have attached the xDataModel.dll file in my xServiceLibrary so that i could query my EF Model.
i am not able to understand the concept. any help would be appreciated.
The problem is that you have two different types named Info: DataModel.Info and ServiceLibrary.Info - because these are different types you cannot cast one into the other.
If there is no strong reason for both being there I would eliminate one of them. Otherwise as a workaround you could project DataModel.Info to ServiceLibrary.Info by copying the relevant properties one by one:
var results = (from qinfo in db.Infoes
select new ServiceLibrary.Info()
{
Scenario_Id = qinfo.Scenario_Id,
//and so on
}).ToList();
The problem is that you have two different classes, both called Info, both in scope at the time you run your query. This is a very very bad thing, especially if you thought they were the same class.
If DataModel.Info and ServiceLibrary.Info are the same class, you need to figure out why they are both in scope at the same time and fix that.
If they are different classes, you need to be explicit about which one you are trying to return. Assuming that your EF model includes a set of DataModel.Info objects, your options there are:
Return a List<DataModel.Info> which you can get by calling query.ToList()
Return a List<ServiceLibrary.Info> which you can get by copying the fields from your DataModel.Info objects:
var query = from qinfo in db.Info
select new ServiceLibrary.Info
{
Scenario_Id = q.Scenario_Id,
Scenario_Name = q.Scenario_Name
Company_Name = q.Company_Name
};
Return something else, such as your custom DTO object, similar to #2 but with only the specific fields you need (e.g. if ServiceLibrary.Info is a heavy object you don't want to pass around.
In general, though, your problem is centered around the fact that the compiler is interpreting List<Info> as List<ServiceLibrary.Info> and you probably don't want it to.

Invalid index n for this SqlParameterCollection with Count=m

I'm getting this nasty error in Castle Active Record (wrapped around NHibernate) when I try to save a class:
Invalid index n for this SqlParameterCollection with Count=m
I know that this error is caused by a property being mapped multiple times in a class however I'm not sure how to get around it. I have two child classes that both map back to the class in question using the same column (IpAddressNumber). Also IpAddressNumber is the primary key of the class, which results in NHibernate trying to map the IpAddressNumber property three times (just a guess.)
Here is the class:
[ActiveRecord(Lazy=true)]
public class DeviceConfiguration : UsersDatabase<DeviceConfiguration>
{
[PrimaryKey]
public virtual long IPAddressNumber { get; set; }
[BelongsTo("IPAddressNumber", Lazy = FetchWhen.OnInvoke)]
public virtual Vehicle Vehicle { get; set; }
[BelongsTo("IPAddressNumber", Lazy = FetchWhen.OnInvoke)]
public virtual JBusConfiguration JBusConfiguration { get; set; }
}
Any help would be greatly appreciated...
I ended up having to just remove the second association altogether to get around this issue. Not a great solution but the only one I could find.

Mapping a dictionary in Fluent Nhibernate through a secondary key

I have a legacy DB which uses a guid to map children to the parent entity.
In my domain layer, I'd prefer to obscure this quirk, so I'd like to have my parent entity look like this:
public class Parent
{
virtual public int Id {get; protected set; }
virtual public string ParentContent { get; set; }
virtual public Guid ReferenceId { get; set; }
virtual public IDictionary<int,Child> Children { get; set; }
}
public class Child
{
virtual public int Id { get; protected set; }
virtual public Parent { get; set; }
virtual public string ChildContent { get; set; }
}
The parent would then map each Child.Id to Child in the Children dictionary. The Child mapping works fine, but I can't seem to find a reasonable mapping for the parent.
A field named ParentReferenceID exists in both Parent and Child tables, so I've attempted to map this with something like this:
mapping.HasMany<Broker>(x => x.Children)
.Table("Child")
.KeyColumn("ParentReferenceID")
.Inverse()
.AsMap<long>(index=>index.Id,val=>val.Type<Broker>());
Unfortunately, this produces an error:
The type or method has 2 generic parameter(s), but 1 generic argument(s) were provided. A generic argument must be provided for each generic parameter.
To simplify my problem, I started by trying Bag semantics, replacing the Parent's IDictionary with an IList. This was mapped using something like:
mapping.HasMany<Broker>(x => x.Brokers)
.Table("Child")
.KeyColumn("ParentReferenceId")
.Inverse()
.AsBag();
That produces the more obvious exception,
System.Data.SqlClient.SqlException: Operand type clash: uniqueidentifier is incompatible with int
Unfortunately, I can't seem to figure out the right way to tell it to join on the ReferenceID field. What's the right way to do that? I'd prefer the dictionary, but I'd be reasonably happy if I could even get the bag to work.
For clarity, I'm using a build of Fluent that is bundled with a recent SharpArchitecture pulled from git. The Fluent dll is marked version 1.0.0.594, but if a more recent build would help, I'm flexible.
Further digging has led me to a solution for the Bag case, though the dictionary is still giving me a bit of trouble.
The solution requires a patch to Fluent NHibernate's OneToManyPart mapping class. (Hat tip to This bug report: Could not map a one-to-many relationship where the key is not the primary key.
mapping.HasMany(x => x.Children)
.Table("Child").KeyColumn("ParentReferenceId")
.PropertyRef("ReferenceId")
.Inverse()
.AsBag();
Theoretically, AsMap should work almost the same way, but for some reason that I'm not entirely clear on, it doesn't work for me. I'll explore that later, but I'm open to suggestions.