I know that this issue has some questions about it, but I can't find the right answer, so please let me ask this question to see if someone could give me the right answer
I have the following scheme for my DB (tables an dsimplified to focus on the problem)
Table Project
idProject INT PK
projectName string UNIQUE
numOfItems INT
Table Item
serialNumber integer PK
idProject integer PK, FK (references idProject table Project)
fileName string PK
Table Analysis
serialNumber integer PK, FK (references serialNumber table Item)
dateMeasure Date PK
fileName string PK
I have those tables coded in C# as follows
class Analysis{
public virtual Item serialNum{ get; set; }
public virtual DateTime dateMeasure { get; set; }
public virtual string fileName { get; set; }
public override int GetHashCode(){
return (fileName.GetHashCode() * serialNum.GetHashCode() * dateMeasure.GetHashCode());
}
public override bool Equals(object obj){
if (obj == null || obj.GetType() != GetType()) return false;
Analysis a = (Analysis)obj;
return (a.serialNum == serialNum && a.fileName == fileName && a.dateMeasure == dateMeasure);
}
}
class Item{
public virtual int serialNumber { get; set; }
public virtual Proyecto idProject { get; set; }
public virtual string fileName { get; set; }
public virtual DateTime measureDate { get; set; }
public override int GetHashCode(){
return (fileName.GetHashCode() * serialNumber.GetHashCode() * idProject.GetHashCode());
}
public override bool Equals(object obj)
{
if (obj == null || obj.GetType() != GetType()) return false;
Item i = (Item)obj;
return (i.serialNumber == serialNumber&& i.fileName== fileName&& d.idProject == idProject);
}
}
class Project
{
public virtual int idProject { get; set; }
public virtual string projectName{ get; set; }
public virtual int numItems { get; set; }
}
And the following mappings of the entites
class AnalysisMap: ClassMap<Analysis>
{
public AnalysisMap()
{
CompositeId()
.KeyReference(x=> x.serialNumber)
.KeyProperty(x => x.dateMeasure)
.KeyProperty(x => x.fileName);
}
}
class ItemMap : ClassMap<Item>
{
public ItemMap()
{
CompositeId()
.KeyProperty(x => x.fileName)
.KeyReference(x => x.idProject)
.KeyProperty(x => x.serialNumber);
Map (x=>x.measureDate).Column("dateMeasure").Not.Nullable();
References(x => x.idProject).Column("idProject");
}
}
class ProjectMap : ClassMap<Project>
{
public ProjectMap()
{
Id(x => x.idProject).GeneratedBy.Identity().Column("idProject");
Map(x => x.projectName).Column("projectName").Unique();
Map(x => x.NumItems).Column("numOfItems").Not.Nullable().Default("0");
}
}
So when I tried to open the session with the following code I get the error "Foreign key (FK9CF1483E7BAABE07:Analysis [serialNum])) must have same number of columns as the referenced primary key (Item [fileName, idProject, serialNumber])"
try{
ISessionFactory sf = Fluently.Configure()
.Database(SQLiteConfiguration.Standard.InMemory().ShowSql()
.ConnectionString("server=local;Data Source= data_source;Integrated Security=SSPI;"))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Project>()
.AddFromAssemblyOf<Item>()
.AddFromAssemblyOf<Analysis>()).BuildSessionFactory();
ISession session = sf.OpenSession();
lblStatus.Text = "OK";
}
catch (Exception ex){
lblStatus.Text = ex.Message.ToString();
}
So how should I get the mapping in order to make this work??
First you got to understand the error, you said:
Table Analysis serialNumber integer PK, FK (references serialNumber
table Item)
This is wrong, serial number is a FK that references serialNumber, idProject and filename, because the three together forms table Item PK. That's why the error says "...must have same number of columns as the referenced primary key (Item [fileName, idProject, serialNumber])", the primary key of table Item is composed by three fields together and not only by "serialNumber" as you have suggested.
Take a look at this link, it explains how to configure a composite foreign key, this is what you need.
Comment bellow if you need any help.
Related
Afternoon all. I'm trying to create a mapping for a flight segment database where at the bottom of the mapping tree a FlightSegment references an origin and destination table with a compositeID consisting of a three letter code and a Boolean determining whether the code is or isn't a city.
Below are the relevant simplified class structures:
public class GTIFlightSegment
{
public virtual int ID { get; protected set; }
public virtual GTIOriginAirport Origin { get; set; }
public virtual GTIDestinationAirport Destination { get; set; }
public virtual GTIFlightSegmentGroup Parent { get; set; }
}
public class GTIAirport
{
public virtual string Code { get; set; }
public virtual string Name { get; set; }
public virtual string City { get; set; }
public virtual string CountryCode { get; set; }
public virtual GTIGeoCode GeoCode {get; set; }
public virtual string Terminal { get; set; }
public virtual bool IsCity { get; set; }
public GTIAirport()
{
GeoCode = new GTIGeoCode();
IsCity = false;
}
public override bool Equals(object obj)
{
var other = obj as GTIAirport;
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return this.Code == other.Code && this.IsCity == other.IsCity;
}
public override int GetHashCode()
{
unchecked
{
int hash = GetType().GetHashCode();
hash = (hash * 31) ^ Code.GetHashCode();
hash = (hash * 31) ^ IsCity.GetHashCode();
return hash;
}
}
}
public class GTIOriginAirport : GTIAirport
{
public virtual GTIFlightSegment Parent { get; set; }
public GTIOriginAirport() : base()
{
}
}
public class GTIDestinationAirport : GTIAirport
{
public virtual GTIFlightSegment Parent { get; set; }
public GTIDestinationAirport() : base()
{
}
}
And below are the mappings I've created so far for the objects:
public class GTIFlightSegmentMap : ClassMap<GTIFlightSegment>
{
public GTIFlightSegmentMap()
{
Id(x => x.ID);
References(x => x.Destination).Columns(new string[] { "DestinationCODE", "DestinationIsCity" }).Cascade.All();
References(x => x.Origin).Columns(new string[] { "OriginCODE", "OriginIsCity"}).Cascade.All();
References(x => x.Parent).Not.Nullable();
}
}
public class GTIAirportMap : ClassMap<GTIAirport>
{
public GTIAirportMap()
{
Table("GTIAirport");
ReadOnly();
CompositeId()
.KeyProperty(x => x.Code, "CODE")
.KeyProperty(x => x.IsCity, "isCity");
Map(x => x.Name).Column("Airport");
Map(x => x.City);
Map(x => x.CountryCode);
Component(x => x.GeoCode, m =>
{
m.Map(x => x.Latitude);
m.Map(x => x.Longitude);
});
}
}
public class GTIOriginAirportMap : SubclassMap<GTIOriginAirport>
{
public GTIOriginAirportMap()
{
KeyColumn("CODE");
KeyColumn("isCity");
HasOne(x => x.Parent).PropertyRef(x => x.Origin);
}
}
public class GTIDestinationAirportMap : SubclassMap<GTIDestinationAirport>
{
public GTIDestinationAirportMap()
{
KeyColumn("CODE");
KeyColumn("isCity");
HasOne(x => x.Parent).PropertyRef(x => x.Origin);
}
}
What I'm trying to achieve is that when a FlightSegment is created in the system it will store the DestinationIsCity/DestinationCode and the OriginIsCity/OriginCode in the flight segments table but not try and update the GTIAirport reference table view. But when the objects are retrieved from the database with a query over, the rich information from the GTIAirport reference table will be fetched.
Or possibly have the Code and IsCity in the DepartureAirport and OriginAirport tables respectively with a ID reference back to the flight segment.
No matter what connotations I'm trying I'm hitting a wall of some kind. Basically I've got myself in a bit of a mess. I've flipped the relationships between the Airport and segment, swapping out to only references. Cascaded, not cascaded.
Common Errors being encountered whilst playing with the mappings:
1) The UPDATE statement conflicted with the FOREIGN KEY constraint
2) {"broken column mapping for: Destination.id of: GilesSabreConnection.Profiling.Model.BookingEngineModel.Model.GTIFlightSegment, type component[Code,IsCity] expects 2 columns, but 1 were mapped"}
3) {"Foreign key (FK582A9C81E6C3913B:GTIFlightSegment [Destination_id])) must have same number of columns as the referenced primary key (GTIDestinationAirport [CODE, isCity])"}
In case it's needed the fluent config is:
return Fluently.Configure().Database(MsSqlConfiguration.MsSql2012.ConnectionString(#"Data Source=Dev2;Initial Catalog=Sandbox;Integrated Security=True")).Mappings(m => m.FluentMappings.AddFromAssemblyOf<Profile>()).ExposeConfiguration(cfg => new SchemaUpdate(cfg).Execute(true, true)).BuildSessionFactory();
Any help to point me in the right direction from the database and fluent gurus would be greatly appreciated.
Many thanks in advance.
Realised that by setting the GTIAirport Map as readonly I was inherently making the Destination and Origin maps as readonly so the mapping could never work no matter how I was configuring the relationships.
So I've split the static reference database of detailed airport info accessed via the View named GTIAiport into two, so the Boolean in the composite key is no longer required. I now have the flight segment mapping simply logging the Airport origin/destination codes within the flight segment table using the Component class in fluent. In the Airport class itself now have a function to independently fetch the rich data from the static reference database table on request using the stored Airport code.
Couldn't figure out a way to do this with fluent. Interested to know if there is a way.
public GTIFlightSegmentMap()
{
Id(x => x.ID);
Component(x => x.Destination, m =>
{
m.Map(y => y.Code).Column("DestinationCode");
});
Component(x => x.Origin, m =>
{
m.Map(y => y.Code).Column("OriginCode");
});
;
References(x => x.Parent).Not.Nullable();
}
}
So I am trying to achieve entity splitting in EF 6.1 with Code First, and I am running into an error.
I have the following tables:
CREATE TABLE [dbo].[Organization]
(
[OrganizationId] INT NOT NULL PRIMARY KEY IDENTITY,
[TenantId] INT NOT NULL,
[Name] NVARCHAR(80) NOT NULL
)
CREATE TABLE [dbo].[OrganizationSettings]
(
[OrganizationSettingsId] INT NOT NULL PRIMARY KEY IDENTITY,
[OrganizationId] INT NOT NULL,
[AllowMultipleTimers] BIT NOT NULL,
CONSTRAINT [FK_OrganizationSettings_Organization] FOREIGN KEY (OrganizationId) REFERENCES Organization(OrganizationId)
)
With the following model objects:
public partial class Organization
{
public int OrganizationId { get; set; }
public int TenantId { get; set; }
public string Name { get; set; }
public OrganizationSettings Settings { get; set; }
}
public class OrganizationSettings
{
public int OrganizationSettingsId { get; set; }
public int OrganizationId { get; set; }
public bool AllowMultipleTimers { get; set; }
}
With the following config code:
var org = modelBuilder.Entity<Organization>();
org.Map(u =>
{
u.Properties(m => new { m.TenantId, m.Name });
})
.ToTable("Organization");
org.Map(u =>
{
u.Property(m => m.Settings.AllowMultipleTimers).HasColumnName("AllowMultipleTimers");
u.ToTable("OrganizationSettings");
});
Then just the following query:
context.Organizations.FirstOrDefault();
Which yields the following error:
The property 'Settings.AllowMultipleTimers' on type 'Organization'
cannot be mapped because it has been explicitly excluded from the
model or it is of a type not supported by the DbModelBuilderVersion
being used.
What am I doing wrong here?
Update: I forgot to mention that I created the database by hand, and am using the CF fluent API to map my models, rather than using "real" Code First.
While I was pretty sure I had this mapping working before, I went ahead and went a little different route.
First I got rid of the surrogate key on `OrganizationSettings (probably not strictly necessary), and then mapped it as an entity with a 1:1 relationship.
My OrganizationSettings is now:
public class OrganizationSettings
{
public int OrganizationId { get; set; }
public bool AllowMultipleTimers { get; set; }
}
OrganizationId is both a primary key and a foreign key.
And the config is:
var org = modelBuilder.Entity<Organization>()
.Map(u =>
{
u.Properties(m => new { m.TenantId, m.Name });
})
.HasRequired(m => m.Settings)
.WithRequiredPrincipal();
modelBuilder.Entity<OrganizationSettings>()
.HasKey(m => m.OrganizationId);
And this seems to work just fine. Since I'm not exposing a DbSet for OrganizationSettings it keeps the conceptual modeling of OrganizationSettings as a value object intact.
Were you trying to set up OrganizationSettings as a complex type while using entity splitting as well? Something like this, perhaps:
public partial class Organization
{
public int OrganizationId { get; set; }
public int TenantId { get; set; }
public string Name { get; set; }
public OrganizationSettings Settings { get; set; }
}
public class OrganizationSettings
{
public bool AllowMultipleTimers { get; set; }
}
// if you don't have a key defined on OrganizationSettings, this might not be needed
modelBuilder.ComplexType<OrganizationSettings>();
modelBuilder.Entity<Organization>()
.Map(u =>
{
u.Properties(m => new { m.OrganizationId, m.TenantId, m.Name });
u.ToTable("Organization");
})
.Map(u =>
{
u.Properties(m => new { m.OrganizationId, m.Settings.AllowMultipleTimers });
u.ToTable("OrganizationSettings");
// If you wanted to set the key column name
u.Property(m => m.OrganizationId).HasColumnName("OrganizationSettingsId");
});
I am using Entity Framework 4.3 code first using an already existing database.
There is a Users table that has the following columns:
- UserID (int)
- FirstName (string)
- Surname (string)
I have an association table called Impersonations. The Impersonations table is an association table between a user table and the same user table. A user can have a list of users. Here is the Impersonations table structure:
- ImpersonateID (int primary key)
- UserID (int FK to Users table's UserID column)
- ImpersonatedUserID (int FK to Users table's UserID column)
I have a User class with properties that I want mapped to these columns:
public class User : IEntity
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmployeeNumber { get; set; }
public virtual ICollection<User> ImpersonatedUsers { get; set; }
public virtual ICollection<User> Users { get; set; }
}
In my db context class I have the following:
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new UserConfiguration());
}
User configuration:
class UserConfiguration : EntityTypeConfiguration<User>
{
internal UserConfiguration()
{
this.Property(x => x.Id).HasColumnName("UserID");
this.Property(x => x.LastName).HasColumnName("Surname");
this.Property(x => x.EmployeeNumber).HasColumnName("StaffNumber");
this.HasMany(i => i.Users)
.WithMany(c => c.ImpersonatedUsers)
.Map(mc =>
{
mc.MapLeftKey("UserID");
mc.MapRightKey("ImpersonatedUserID");
mc.ToTable("Impersonations");
});
}
}
Did I link this up correctly using Entity Framework? If I pass through a user id then a list of users needs to be returned that was marked as inpersonated users. How I do this? I have this but both User and ImpersonatedUsers are empty:
return DbContext.Users
.Include("ImpersonatedUsers")
.SingleOrDefault(x => x.Id == userId);
Lets say I have the following data in my Users table (id, first name, last name, employee number):
7 Craig Matthews 123456
8 Susan Renshaw 234567
9 Michelle du Toit 34567
And the following data in my Impersonations table (impersonated id, user id, impersonated user id):
1 7 8
2 7 9
So if I pass in a user id of 7 then it need to return records for users Susan Renshaw and Michelle du Toit.
Just for clarity if you are still confused...
I have a similar situation. I have a Products table and a Specifications table. These 2 are linked up by the assication table called ProductSpecifications. I am trying to achieve the same here, but the 2 tables would be the Users table and the association table is Impersonations.
If I well understand, I think I have quite the same: a user is also a group and so can have members.
Here is an extract of my code:
public partial class User : AuthorizableBaseObject, IHasUID {
public User() {
Members = new List<User>();
}
public Guid UID { get; set; }
public DateTime EmailValidationDate { get; set; }
public String EMail { get; set; }
//public Int64 Id { get; set; }
public String Login { get; set; }
public String Password { get; set; }
public String Description { get; set; }
public DateTime LastConnectionDate { get; set; }
public Boolean CanConnect { get; set; }
public Boolean IsDisabled { get; set; }
public virtual List<User> Members { get; set; }
}
with the following configuration :
public class UserConfiguration : EntityTypeConfiguration<VDE.User> {
public UserConfiguration()
: base() {
ToTable("Users", "dbo");
Property(u => u.EMail).IsRequired().HasColumnType("nvarchar").HasMaxLength(100);
Property(u => u.Login).IsRequired().HasColumnType("nvarchar").HasMaxLength(20);
Property(u => u.Password).IsRequired().HasColumnType("nvarchar").HasMaxLength(50);
Property(u => u.Description).HasColumnType("nvarchar").HasMaxLength(200);
Property(u => u.LastConnectionDate).HasColumnType("datetime2");
HasMany(u => u.Members).WithMany().Map(m => m.MapLeftKey("UserId").MapRightKey("MemberId").ToTable("UserMembers"));
}
}
From here to get the members of a group the query is easy:
context.Users.Where(u => u.Id == someId).Select(u => u.Members).FirstOrDefault()
This will give an IEnumerable
Try taking a look at this page on inheritance. Your explanation isn't great, but I think this is what you're trying to achieve.
You must create a class for Impersonation and add it as a DBSet to the dbcontext. EF may make you put a [Key] attribute on the foreign key fields, along with [Column(Order = 0 or 1)].
Then you can lazy load the property:
public virtual List<Impersonation> UserImpersonations
{
get
{
if(_userImpersonations == null)
{
// Set _userImpersonations =
// lazy load using a linq to sql query where
// UserImpersonations.UserId = this.UserId
}
return __userImpersonations;
}
}
We have a legacy Database that we want to read data from using NHibernate.
The tables that we want to map are the following:
Users
PK - UserId
PK - GroupId
LocationSource
etc...
Locations
PK - UserId
PK - GroupId
PK - Source
X
Y
Every user has one or more locations. A location can be entered from different sources, which are identified by the Source column.
the Users table's LocationSource column holds the most relevant location source for that user.
In the current application we're writing, we need only the last location.
this is done mainly for performance reasons, we don't want to load all the locations (using outer join)
whenever we load a User (Lazy Loading is out of the question either).
The classes will look something like that:
public class UserKey
{
public int UserId {get;set;}
public int GroupId {get;set;
}
public class Location
{
public double X {get;set;}
public double Y {get;set;}
public LocationSource Source {get;set;}
}
public class User
{
public UserKey Id {get; set;}
public Location Location {get;set;}
}
I cannot figure out how to map the database scheme to those class.
Everything I tried failed so far.
I will appreciate your help.
Here's how I would do it.
User would contain both a List (Locations) and a reference to the current Location (Source) therefore you get the current Location per User and the historic list of a User's Location's.
User.Locations and User.Source will both lazy load by default but you can use any of the query options to eager load User.Source to get the current location for your benefit.
When you add a Location to a User via the Locations property you will obviously need to manage the Source reference as well.
If you would like the XML mapping files I can provide as well as I have used Fluent NHibernate 1.1.
public class User
{
public virtual int UserId { get; set; }
public virtual int GroupId { get; set; }
public virtual IList<Location> Locations { get; set; }
public virtual Location Source { get; set; }
public override bool Equals(object obj)
{
if (obj == null)
return false;
var t = obj as User;
if (t == null)
return false;
if (UserId == t.UserId && GroupId == t.GroupId)
return true;
return false;
}
public override int GetHashCode()
{
return (UserId + "|" + GroupId).GetHashCode();
}
}
public class Source
{
public virtual int Id { get; set; }
}
public class Location
{
public virtual User User { get; set; }
public virtual int Id { get; set; }
public virtual Source Source { get; set; }
public virtual string X { get; set; }
public virtual string Y { get; set; }
public override bool Equals(object obj)
{
if (obj == null)
return false;
var t = obj as Location;
if (t == null)
return false;
if (User == t.User && Source == t.Source)
return true;
return false;
}
public override int GetHashCode()
{
return (User.GetHashCode() + "|" + Id).GetHashCode();
}
}
public class UserMap : ClassMap<User>
{
public UserMap()
{
CompositeId()
.KeyProperty(x => x.UserId, "UserId")
.KeyProperty(x => x.GroupId, "GroupId");
HasMany(x => x.Locations);
References(x => x.Source).Columns("UserId", "GroupId", "LocationSource");
}
}
public class LocationMap : ClassMap<Location>
{
public LocationMap()
{
CompositeId()
.KeyReference(x => x.Source, "Source")
.KeyReference(x => x.User,"groupId","userid");
References(x => x.User).Columns("userid","groupid");
}
}
public class SourceMap : ClassMap<Source>
{
public SourceMap()
{
Id(x => x.Id).GeneratedBy.Native();
}
}
Problem:
There are searches that can be stored in the DB. Each search has a collection of filters. Also there are roles. Each role may have (nullable column) a default search assigned to it. Also, each search is visible to zero or many roles (many-to-many relationship).
When I try to access the search filters, NH tries to access filters.DefaultSearchId, which doesn't exist in filters table.
DB:
CREATE TABLE [dbo].[Searches]
(
Id int identity(1,1) primary key,
Description nvarchar(2000) not null
);
CREATE TABLE [dbo].[Filters]
(
Id int identity(1,1) primary key,
Description nvarchar(2000) not null,
SearchId int not null references Searches(Id)
);
CREATE TABLE [dbo].[Roles]
(
Id int identity(1,1) primary key,
Name nvarchar(255) not null,
DefaultSearchId int null references Searches(Id)
);
CREATE TABLE [dbo].[SearchesRoles]
(
SearchId int not null references Searches(Id),
RoleId int not null references Roles(Id)
);
Entities:
public class Search {
public virtual int Id { get; set; }
public virtual string Description { get; set; }
public virtual ICollection<Filter> Filters { get; set; }
public virtual ICollection<Role> Roles { get; set; }
}
public class Filter {
public virtual int Id { get; set; }
public virtual string Description { get; set; }
public virtual Search Search { get; set; }
}
public class Role {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Search DefaultSearch { get; set; }
}
Mappings:
public class SearchMap : ClassMap<Search>{
public SearchMap() {
Table("Searches");
Id(x => x.Id).GeneratedBy.Identity();
Map(x => x.Description);
HasMany(x => x.Filters).Inverse().Cascade.All().AsBag();
HasManyToMany(x => x.Roles).Table("SearchesRoles").ParentKeyColumn("SearchId").ChildKeyColumn("RoleId");
}
}
public class FilterMap : ClassMap<Filter> {
public FilterMap() {
Table("Filters");
Id(x => x.Id).GeneratedBy.Identity();
Map(x => x.Description);
References(x => x.Search).Column("SearchId");
}
}
public class RoleMap : ClassMap<Role> {
public RoleMap() {
Table("Roles");
Id(x => x.Id).GeneratedBy.Identity();
Map(x => x.Name);
References(x => x.DefaultSearch).Column("DefaultSearchId");
}
}
Code:
class Program {
static void Main() {
var sessionFactory = CreateSessionFactory();
using (var session = sessionFactory.OpenSession()) {
var search = session.Get<Search>(1);
foreach (var filter in search.Filters) {
Console.WriteLine(filter);
}
}
}
static ISessionFactory CreateSessionFactory(){
string connectionString = #"server=.\sql2008; user id = sa; pwd=1; database = nhbug;";
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(connectionString))
.Mappings(m=>m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly())).BuildSessionFactory();
}
}
ERROR:
When accessing the search.Filters property, NHibernate tries to access Filters.DefaultSearchId db column which is not supposed to be there. This column exists in Roles table but not in filters.
QUESTION:
Is it invalid configuration, Fluent NHibernate or NHibernate bug?
I'm using SQL Server 2008 R2, NHibernate 2.1.2 and Fluent NHibernate 1.1.0.685, although this issue exists in NHibernate 3 beta 2 as well.
Thank you.
UPDATE:
Here is the actual SQL generated
UPDATE2: CDMDOTNET, same error, same sql, unfortunately.
UPDATE3: Actual exception
UPDATE4: This is a particular use case of a general bug: Entity references other entities as 'many-to-many' and on the other side of 'many-to-many' assoc. the other entity references the source entity (DefaultQuery in my case). NH goes nuts when accessing any child collection (one-to-many) of a source entity (Filters in my case).
UPDATE5: Sample data
UPDATE6: XML issued by Fluent NHibernate
Update the HasMany mapping on the SearchMap to include the KeyColumn():
HasMany(x => x.Filters).KeyColumn("SearchId").Inverse().Cascade.All().AsBag();
You didn't specify the column name for the Filters bag. It should be set to SearchId.