ServiceStack OrmLite Join Issues - c#

I'm having a problem with ServiceStack OrmLite for SQL Server in a Visual Studio 2013 C# project. My problem is that I'm trying to use the SqlExpression builder and it's not capturing my table schema and the generated SQL code is not correct. When I run the code, I get a System.Data.SqlClient.SqlException that says "Invalid object name 'ReportPages'."
I'm using the latest NuGet version of ServiceStack.OrmLite, which is version 4.0.24.
Let me start with the table setup. Note that I removed the foreign keys for convenience:
-- Create the report pages table.
CREATE TABLE [MicroSite].[ReportPages](
[ReportPageID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](200) NULL,
[Template] [nvarchar](50) NULL,
[AccessLevel] [int] NOT NULL,
[AssignedEmployeeId] [int] NOT NULL,
[Disabled] [bit] NOT NULL,
[Deleted] [bit] NOT NULL,
[ReportSectionID] [int] NOT NULL,
[Index] [int] NOT NULL,
[Cover] [bit] NOT NULL,
CONSTRAINT [PK_dbo.ReportSections] PRIMARY KEY CLUSTERED
(
[ReportPageID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
-- Create the report sections table.
CREATE TABLE [MicroSite].[ReportSections](
[ReportSectionID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](100) NULL,
[ReportID] [int] NOT NULL,
CONSTRAINT [PK_dbo.ReportSectionGroups] PRIMARY KEY CLUSTERED
(
[ReportSectionID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
-- Create the report editables table.
CREATE TABLE [MicroSite].[Editables](
[EditableID] [int] IDENTITY(1,1) NOT NULL,
[Index] [int] NOT NULL,
[Content] [nvarchar](max) NULL,
[Styles] [nvarchar](100) NULL,
[Type] [int] NOT NULL,
[ReportPageID] [int] NOT NULL,
CONSTRAINT [PK_dbo.Editables] PRIMARY KEY CLUSTERED
(
[EditableID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
So my tables basically look like this:
Here are my POCOs:
[Alias("ReportPages")]
[Schema("MicroSite")]
public partial class MicrositeReportPage : IHasId<int>
{
[Required]
public int AccessLevel { get; set; }
[Required]
public int AssignedEmployeeId { get; set; }
[Required]
public bool Cover { get; set; }
[Required]
public bool Deleted { get; set; }
[Required]
public bool Disabled { get; set; }
[Alias("ReportPageID")]
[AutoIncrement]
[PrimaryKey]
public int Id { get; set; }
[Required]
public int Index { get; set; }
public string Name { get; set; }
[Alias("ReportSectionID")]
[Required]
public int ReportSectionId { get; set; }
public string Template { get; set; }
}
[Alias("ReportSections")]
[Schema("MicroSite")]
public class MicrositeReportSection : IHasId<int>
{
[Alias("ReportSectionID")]
[AutoIncrement]
[PrimaryKey]
public int Id { get; set; }
public string Name { get; set; }
[Alias("ReportID")]
[Required]
public int ReportId { get; set; }
}
[Alias("Editables")]
[Schema("MicroSite")]
public partial class MicrositeEditable : IHasId<int>
{
public string Content { get; set; }
[Alias("EditableID")]
[AutoIncrement]
[PrimaryKey]
public int Id { get; set; }
[Required]
public int Index { get; set; }
[Alias("ReportPageID")]
[Required]
public int ReportPageId { get; set; }
public string Styles { get; set; }
[Alias("Type")]
[Required]
public int TypeId { get; set; }
}
The actual SQL statement I want to generate is this:
SELECT e.EditableID
, e.[Index]
, e.Content
, e.Styles
, e.Type
, e.ReportPageID
FROM
MicroSite.ReportSections AS rs
LEFT JOIN
MicroSite.ReportPages AS rp ON rp.ReportSectionID = rs.ReportSectionID AND rp.[Index] = 24
LEFT JOIN
MicroSite.Editables AS e ON e.ReportPageID = rp.ReportPageID
WHERE
rs.ReportID = 15
Here is my C# code:
var query = db.From<MicrositeReportSection>()
.LeftJoin<MicrositeReportSection, MicrositeReportPage>((section, page) => section.Id == page.ReportSectionId)
.LeftJoin<MicrositeReportPage, MicrositeEditable>((page, editable) => page.Id == editable.ReportPageId && page.Index == 24)
.Where<MicrositeReportSection>(section => section.ReportId == 15);
var sql = query.ToSelectStatement();
var result = db.Select<MicrositeEditable>(query)
The generated SQL statement from the sql variable looks like this (I formatted it for readability):
SELECT
"ReportSectionID",
"Name",
"ReportID"
FROM
"MicroSite"."ReportSections"
LEFT JOIN
"ReportPages" ON ("ReportSections"."ReportSectionID" = "ReportPages"."ReportSectionID")
LEFT JOIN "Editables"
ON (("ReportPages"."ReportPageID" = "Editables"."ReportPageID") AND ("ReportPages"."Index" = 24))
WHERE
("ReportSections"."ReportID" = 15)
First, the left joins are missing the schema name, which makes the SQL statement incorrect. Second, what's going on in the select statement? Those aren't the columns from the MicrositeEditable table. Am I doing this correctly or is this an actual bug with OrmLite?

I submitted a ticket with the development team and this is now fixed in version 4.0.25.

Related

Why EF Core database first foreign key is not working as expected here?

I am using EF Core Database First Approach, where I have a one to many relationship in two tables.
visit and expense_details table.
Here one visit may have zero or multiple entry in expense_details table
I defined foreign key relationship between those, but, when I run the project the resulted JSON returns NULL for Visit property in Expense_details object and same happens in case of expense property in Visit Object.
My Database Objects are:
CREATE TABLE [dbo].[visit](
[id] [int] IDENTITY(1,1) NOT NULL,
[user_id] [int] NOT NULL,
[tour_id] [int] NULL,
[description] [varchar](200) NULL,
[subject_to] [varchar](50) NOT NULL,
[start_date] [date] NOT NULL,
[start_time] [varchar](50) NOT NULL,
[end_time] [varchar](50) NULL,
[start_location] [varchar](50) NULL,
[destination_location] [varchar](50) NOT NULL,
[start_mileage] [decimal](18, 0) NOT NULL,
[end_mileage] [decimal](18, 0) NOT NULL,
CONSTRAINT [PK_visit] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[expense_details](
[id] [int] IDENTITY(1,1) NOT NULL,
[visit_id] [int] NOT NULL,
[expense_category_id] [int] NOT NULL,
[expense_amount] [numeric](18, 0) NOT NULL,
[remarks] [varchar](200) NULL,
CONSTRAINT [PK_expense_details] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[expense_details] WITH CHECK ADD CONSTRAINT [FK_expense_details_visit] FOREIGN KEY([visit_id])
REFERENCES [dbo].[visit] ([id])
GO
ALTER TABLE [dbo].[expense_details] CHECK CONSTRAINT [FK_expense_details_visit]
GO
These are the generated Model class after scaffolding db
public partial class Visit
{
public Visit()
{
ExpenseDetails = new HashSet<ExpenseDetail>();
}
public int Id { get; set; }
public int UserId { get; set; }
public int? TourId { get; set; }
public string Description { get; set; }
public string SubjectTo { get; set; }
public DateTime StartDate { get; set; }
public string StartTime { get; set; }
public string EndTime { get; set; }
public string StartLocation { get; set; }
public string DestinationLocation { get; set; }
public decimal StartMileage { get; set; }
public decimal EndMileage { get; set; }
public virtual ICollection<ExpenseDetail> ExpenseDetails { get; set; }
}
}
public partial class ExpenseDetail
{
public int Id { get; set; }
public int VisitId { get; set; }
public int ExpenseCategoryId { get; set; }
public decimal ExpenseAmount { get; set; }
public string Remarks { get; set; }
public virtual Visit Visit { get; set; }
}
}
ModelBuilder objects are:
modelBuilder.Entity<ExpenseDetail>(entity =>
{
entity.ToTable("expense_details");
entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.ExpenseAmount)
.HasColumnType("numeric(18, 0)")
.HasColumnName("expense_amount");
entity.Property(e => e.ExpenseCategoryId).HasColumnName("expense_category_id");
entity.Property(e => e.Remarks)
.HasMaxLength(200)
.IsUnicode(false)
.HasColumnName("remarks");
entity.Property(e => e.VisitId).HasColumnName("visit_id");
entity.HasOne(d => d.Visit)
.WithMany(p => p.ExpenseDetails)
.HasForeignKey(d => d.VisitId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_expense_details_visit");
});
[HttpGet]
public IEnumerable<Visit> Get()
{
var visit = tourActivityExpenseContext.Visits
.Include(e => e.ExpenseDetails)
.ToList();
return visit;
}
I am not sure if I need to manually impose something in code?

Parent Reference in Query DB when Creating database in LINQ

I have the following Classes
public class Children {
public Children (){} // constructor
public int Id {get;set;},
public string ChildName {get; set;}
}
public class Parents {
public Parents(){} // constructor
public int Id {get;set;},
public string ParentName {get;set;}
public Children Child {get; set;}
}
I want 1 child per parent, In the configuration I have
public void Configure(EntityTypeBuilder<Parents> configuration)
{
configuration.ToTable("Parents");
configuration.Property(p => p.Id).HasField("_id");
configuration.HasOne(a => a.ChildClass).WithMany().OnDelete(DeleteBehavior.Cascade);
}
public void Configure(EntityTypeBuilder<Children> configuration)
{
configuration.ToTable("Children");
configuration.Property(p => p.Id).HasField("_id");
}
When I use the entity framework 5 builder I get 2 tables back from the database
CREATE TABLE [dbo].[Parents](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ChildId] [int] NOT NULL,
[ParentName] [nvarchar](max) NULL,
CONSTRAINT [PK_Parents] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
WITH
(PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
ALTER TABLE [dbo].[Parents] WITH CHECK ADD CONSTRAINT
[FK_Parents_Children_Child] FOREIGN KEY([ChildId])
REFERENCES [dbo].[Children] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Parents] CHECK CONSTRAINT [FK_Parents_Parents_Children_ChildId]
GO
CREATE TABLE [dbo].[Children](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ChildName] [nvarchar](max) NULL,
[ParentId] [int] NULL,
CONSTRAINT [PK_Children] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[Children] WITH CHECK ADD CONSTRAINT [FK_Children_Parent_ParentId] FOREIGN
KEY([ParentId])
REFERENCES [dbo].[Parents] ([Id])
GO
ALTER TABLE [dbo].[Children] CHECK CONSTRAINT [FK_Children_Parent_ParentId]
GO
Basically I get stuck in a loop as I cannot insert a Parents record, and I cannot insert a son as they need both sets of Id's, I dont know why the Children table needs a reference to the Parents table, if the parents table already references the Children table.
Based on your fluent mapping, it looks like you've set up a one-to-many relationship, where each child can have many parents. But you actually want a one-to-one relationship.
public class Children {
public Children (){}
public int Id { get;set; }
public string ChildName { get; set; }
public int ParentId { get; set; }
public Parents Parent { get; set; }
}
public class Parents {
public Parents(){}
public int Id { get; set; }
public string ParentName { get; set; }
public Children Child { get; set; }
}
public void Configure(EntityTypeBuilder<Parents> configuration)
{
configuration.ToTable("Parents");
configuration.Property(p => p.Id).HasField("_id");
configuration.HasOne(p => p.Child).WithOne(c => c.Parent).HasForeignKey<Children>(c => c.ParentId).OnDelete(DeleteBehavior.Cascade);
}
However, the generated SQL doesn't seem to match your model nor your fluent configuration.

The INSERT statement conflicted with the FOREIGN KEY SAME TABLE constraint | ASP.NET Core & Entity Framework Core Code First

I have a table named Company
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Companies](
[Id] [uniqueidentifier] NOT NULL,
[ActiveStatus] [nvarchar](max) NULL,
[Name] [nvarchar](max) NULL,
[Address] [nvarchar](max) NULL,
[Phone1] [nvarchar](max) NULL,
[Phone2] [nvarchar](max) NULL,
[Email] [nvarchar](max) NULL,
[CompanyId] [uniqueidentifier] NOT NULL,
[IsParent] [nvarchar](max) NULL,
CONSTRAINT [PK_Companies] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[Companies] WITH CHECK ADD CONSTRAINT [FK_Companies_Companies_CompanyId] FOREIGN KEY([CompanyId])
REFERENCES [dbo].[Companies] ([Id])
GO
ALTER TABLE [dbo].[Companies] CHECK CONSTRAINT [FK_Companies_Companies_CompanyId]
GO
I made this using ASP.NET Core code first, this is my class
public class BaseClass
{
[Key]
public Guid Id { get; set; }
public string ActiveStatus { get; set; }
}
public class Company: BaseClass
{
public string Name { get; set; }
public string Address { get; set; }
public string Phone1 { get; set; }
public string Phone2 { get; set; }
public string Email { get; set; }
[ForeignKey("Company")]
public Guid CompanyId { get; set; }
public Company ParentCompany { get; set; }
public string IsParent { get; set; }
public ICollection<Company> ParentCompanies { get; set; }
public ICollection<Activity> Activities { get; set; }
public ICollection<Order> Orders { get; set; }
public ICollection<Ticket> Tickets { get; set; }
public ICollection<User> Users { get; set; }
}
I want to insert data to my table using a query
INSERT [dbo].[Companies] ([Id], [ActiveStatus], [Name], [Address], [Phone1], [Phone2], [Email], [CompanyId], [IsParent]) VALUES (N'af85a23c-3832-47c9-3efe-08d79f1b5659', N'Active', N'PT. Sari Coffee Indonesia', N'Sahid Sudirman Center 27th Floor, Jl. Jend. Sudirman No.Kav. 86, RT.10/RW.11, Karet Tengsin, Kota Jakarta Pusat, Daerah Khusus Ibukota Jakarta 10220', N'+62 21 574 6501', N'+62 21 574 5808', N'feedback#starbucks.co.id', N'00000000-0000-0000-0000-000000000000', N'1')
GO
But I got an error:
Msg 547, Level 16, State 0, Line 3 The INSERT statement conflicted
with the FOREIGN KEY SAME TABLE constraint
"FK_Companies_Companies_CompanyId". The conflict occurred in database
"CRMandOMS", table "dbo.Companies", column 'Id'. The statement has
been terminated.
Please help
You wanna add 00000000-0000-0000-0000-000000000000 as a CompanyId, so you faced with this error occurs because in your table there is no company with this Id.
In your scenario there is a possibility of having a company with no parent, so your table design is wrong. for resolving this error you have to make the CompanyId foreign key nullable.
do like below:
...
[ForeignKey("Company")]
public Guid? CompanyId { get; set; }
...
Then Add-Migration and Update-Database for changing the database. Now, you can insert a company with Null parent.
good luck

Sql mapping problems

I have CustomDBContext:
public class CustomDBContext : DbContext
{
public CustomDBContext(string connectionString)
: base(connectionString)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
......
modelBuilder.Entity<KeyProd>().ToTable("KeyProd");
......
}
}
And Repository registration in Startup.cs:
.....
var builder = new ContainerBuilder();
builder.Register(c => RepositoryFactory.GetInstance<KeyProd, long>("ef")).As<IRepository<KeyProd, long>>().InstancePerRequest();
After injection of this repository to my service, i try to add new row to database:
_keyProductionRepository.Add(new KeyProd
{
Id = key.Id,
Comment = key.Comment,
CreatedBy = adminId,
DateCreated = DateTime.UtcNow,
KeyType = key.KeyType,
PageId = key.PageId,
Name = key.Name
});
The exception is:
Cannot insert the value NULL into column 'Id', table 'ln_resources.dbo.KeyProd'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated.
The model i try to insert have id (3). Is not null.I checked it in debug mode.
My table in SQl without autoincremented Id. This is a query of table:
CREATE TABLE [dbo].[KeyProd](
[Id] [bigint] NOT NULL,
[Name] [nvarchar](100) NULL,
[KeyType] [int] NOT NULL,
[Comment] [text] NULL,
[PageId] [int] NOT NULL,
[CreatedBy] [int] NOT NULL,
[DateCreated] [datetime] NOT NULL DEFAULT (getdate()),
[DateUpdated] [datetime] NULL DEFAULT (getdate()),
[UpdatedBy] [int] NULL,
PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
GO
ALTER TABLE [dbo].[KeyProd] WITH CHECK ADD CONSTRAINT [FK_KeyProd_Page] FOREIGN KEY([PageId])
REFERENCES [dbo].[Page] ([Id])
GO
ALTER TABLE [dbo].[KeyProd] CHECK CONSTRAINT [FK_KeyProd_Page]
GO
My KeyProd Class:
public class KeyProd
{
public long Id { get; set; }
public string Name { get; set; }
public KeyType KeyType { get; set; }
public string Comment { get; set; }
public int PageId { get; set; }
public int CreatedBy { get; set; }
public DateTime DateCreated { get; set; }
public int? UpdatedBy { get; set; }
public DateTime? DateUpdated { get; set; }
}
If i try to insert this model directly from SQL SERVER by using SQL INSERT, all works fine.
Where the problem? Why Id is Null? Why mapping not working.
You may need to annotate the key field on KeyProd to indicate that you don't want the value to be automatically generated by your context. Try adding DatabaseGeneratedOption.None to your key property.
public class KeyProd {
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public long Id { get; set; }
// ... Other properties
}

Cannot insert the value NULL into column - NHibernate entity with 2 parents

{"Cannot insert the value NULL into column 'RootID', table 'Legacy.dbo.Middle'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated."}
I have a Root class, Middle class, and 'bottom' class. The root class as "Middle" as children, then Middle has "Bottom" as children. However, in this legacy database with poor design there is also a reference to "Root" from the "Bottom".
root table
CREATE TABLE [dbo].[Root](
[RootID] [int] IDENTITY(1,1) NOT NULL,
[RootName] [varchar](max) NOT NULL,
CONSTRAINT [PK_Root] PRIMARY KEY CLUSTERED
(
[RootID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
middle table
CREATE TABLE [dbo].[Middle](
[MiddleID] [int] IDENTITY(1,1) NOT NULL,
[MiddleName] [varchar](max) NOT NULL,
[RootID] [int] NOT NULL,
CONSTRAINT [PK_Middle] PRIMARY KEY CLUSTERED
(
[MiddleID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
bottom table
CREATE TABLE [dbo].[Bottom](
[BottomID] [int] IDENTITY(1,1) NOT NULL,
[BottomName] [varchar](max) NOT NULL,
[MiddleID] [int] NOT NULL,
[RootID] [int] NOT NULL,
CONSTRAINT [PK_Bottom] PRIMARY KEY CLUSTERED
(
[BottomID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
the foreign keys
ALTER TABLE [dbo].[Middle] WITH CHECK ADD CONSTRAINT [FK_Middle_Root] FOREIGN KEY([RootID])
REFERENCES [dbo].[Root] ([RootID])
GO
ALTER TABLE [dbo].[Middle] CHECK CONSTRAINT [FK_Middle_Root]
ALTER TABLE [dbo].[Bottom] WITH CHECK ADD CONSTRAINT [FK_Bottom_Middle] FOREIGN KEY([MiddleID])
REFERENCES [dbo].[Middle] ([MiddleID])
GO
ALTER TABLE [dbo].[Bottom] CHECK CONSTRAINT [FK_Bottom_Middle]
GO
ALTER TABLE [dbo].[Bottom] WITH CHECK ADD CONSTRAINT [FK_Bottom_Root] FOREIGN KEY([RootID])
REFERENCES [dbo].[Root] ([RootID])
GO
ALTER TABLE [dbo].[Bottom] CHECK CONSTRAINT [FK_Bottom_Root]
c# entities
public class Root
{
public Root()
{
Middles = new SortedSet<Middle>();
}
public int RootID { get; set; }
public string RootName { get; set; }
public ISet<Middle> Middles { get; set; }
}
public class Middle
{
public Middle()
{
Bottoms = new SortedSet<Bottom>();
}
public int MiddleID { get; set; }
public Root Root
{
get;
set;
}
public string MiddleName { get; set; }
public ISet<Bottom> Bottoms { get; set; }
}
public class Bottom
{
public int BottomID { get; set; }
public Root Root { get; set; }
public Middle Middle { get; set; }
public string BottomName { get; set; }
}
I am using the following mappings via FluentNHibernate, but I've tried a ton of variations and just cannot get it to work in any way.
public class RootMap : IAutoMappingOverride<Root>
{
public void Override(AutoMapping<Root> mapping)
{
mapping.Not.LazyLoad();
mapping.Id(x => x.RootID);
mapping.HasMany(x => x.Middles).KeyColumn("RootID").Cascade.AllDeleteOrphan().Inverse();
}
}
public class MiddleMap : IAutoMappingOverride<Middle>
{
public void Override(AutoMapping<Middle> mapping)
{
mapping.Not.LazyLoad();
mapping.Id(x => x.MiddleID);
mapping.References(x => x.Root);
mapping.HasMany(x => x.Bottoms).KeyColumn("MiddleID").Cascade.AllDeleteOrphan();
}
}
public class BottomMap : IAutoMappingOverride<Bottom>
{
public void Override(AutoMapping<Bottom> mapping)
{
mapping.Not.LazyLoad();
mapping.Id(x => x.BottomID);
mapping.References(x => x.Root);
mapping.References(x => x.Middle);
}
}
You need to declare the many valued side of the relation as "inverse". See last paragraph of section 6.4: http://nhibernate.info/doc/nh/en/index.html#collections-onetomany

Categories

Resources