{"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
Related
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.
I'm having troubles figuring out why I can save directly to the collection with ontext.CommunicationPreferences.Add. But Trying to add to guest.communicationPreference does not work.
Am I missing some mapping somewhere? Thanks!
Code
[TestMethod]
public void TestMethod1()
{
var guests = new Context().Guests.ToList();
var communicationTypes = new Context().CommunicationTypes.ToList();
var communicationPreferences = new Context().CommunicationPreferences.ToList();
using (var context = new Context())
{
var guest = guests.FirstOrDefault(x => x.Id == 1);
// This works
context.CommunicationPreferences.Add(new CommunicationPreference(1, guest.Id, communicationTypes.First().Id));
// This does not work - why? :(
guest.CommunicationPreference = new CommunicationPreference(1, guest.Id, communicationTypes.First().Id);
context.SaveChanges();
}
}
public class CommunicationPreference
{
public CommunicationPreference()
{
}
public CommunicationPreference(int time, int guestId, int communicationTypeId)
{
Time = time;
GuestId = guestId;
CommunicationTypeId = communicationTypeId;
}
public int GuestId { get; set; }
public int? CommunicationTypeId { get; set; }
public virtual CommunicationType CommunicationType { get; set; }
public virtual Guest Guest { get; set; }
public int? Time { get; set; }
}
public class CommunicationType
{
public CommunicationType()
{
}
public int Id { get; set; }
public string Name { get; set; }
}
public class Guest
{
public Guest()
{
}
public int Id { get; set; }
public string FirstName { get; set; }
public virtual CommunicationPreference CommunicationPreference { get; set; }
}
public class Context : DbContext
{
public Context() : base("Context")
{
}
public DbSet<Models.Guest> Guests { get; set; }
public DbSet<Models.CommunicationType> CommunicationTypes { get; set; }
public DbSet<Models.CommunicationPreference> CommunicationPreferences { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
this.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
modelBuilder.Entity<Models.CommunicationPreference>().HasKey(t => t.GuestId);
modelBuilder
.Entity<Models.CommunicationPreference>()
.HasRequired<Models.Guest>(x => x.Guest)
.WithOptional(x => x.CommunicationPreference);
}
}
Database
CREATE TABLE [dbo].[Guest](
[Id] [int] IDENTITY(1,1) NOT NULL,
[FirstName] [varchar](50) NOT NULL,
CONSTRAINT [PK_Guest] 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]
GO
CREATE TABLE [dbo].[CommunicationType](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_CommunicationType] 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]
GO
CREATE TABLE [dbo].[CommunicationPreference](
[Time] [int] NULL,
[CommunicationTypeId] [int] NULL,
[GuestId] [int] NOT NULL,
CONSTRAINT [PK_CommunicationPreference] PRIMARY KEY CLUSTERED
(
[GuestId] 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
ALTER TABLE [dbo].[CommunicationPreference] WITH CHECK ADD CONSTRAINT [FK_CommunicationPreference_CommunicationType] FOREIGN KEY([CommunicationTypeId])
REFERENCES [dbo].[CommunicationType] ([Id])
GO
ALTER TABLE [dbo].[CommunicationPreference] CHECK CONSTRAINT [FK_CommunicationPreference_CommunicationType]
GO
ALTER TABLE [dbo].[CommunicationPreference] WITH CHECK ADD CONSTRAINT [FK_CommunicationPreference_Guest] FOREIGN KEY([GuestId])
REFERENCES [dbo].[Guest] ([Id])
GO
ALTER TABLE [dbo].[CommunicationPreference] CHECK CONSTRAINT [FK_CommunicationPreference_Guest]
GO
You are loading your data in 4 different context instances....
This:
var guests = new Context().Guests.ToList(); // Context 1
var communicationTypes = new Context().CommunicationTypes.ToList(); // Context 2
var communicationPreferences = new Context().CommunicationPreferences.ToList(); // Context 3
using (var context = new Context()) // Context 4
{
var guest = guests.FirstOrDefault(x => x.Id == 1);
// This works
context.CommunicationPreferences.Add(new CommunicationPreference(1, guest.Id, communicationTypes.First().Id));
// This does not work - why? :(
guest.CommunicationPreference = new CommunicationPreference(1, guest.Id, communicationTypes.First().Id);
context.SaveChanges();
}
Put everything in the same context because Context #4 (using one) doesn't know about entities from Context 1 (guests)
This would work:
using (var context = new Context())
{
var guests = context.Guests.ToList();
var communicationTypes = context.CommunicationTypes.ToList();
var communicationPreferences = context.CommunicationPreferences.ToList();
var guest = guests.FirstOrDefault(x => x.Id == 1);
guest.CommunicationPreference = new CommunicationPreference(1, guest.Id, communicationTypes.First().Id);
context.SaveChanges();
}
I am ignoring every other aspects except why not updating.
When you adding entity by add() it set state of the that entity to modified automatically but if you not using add() then
You need to modify your state of entity manually.
context.Entry(guest.CommunicationPreference).State = EntityState.Modified;
You need to add above line before saving changes.
in this block of code
context.CommunicationPreferences.Add(new CommunicationPreference(1, guest.Id, communicationTypes.First().Id));
// This does not work - why? :(
guest.CommunicationPreference = new CommunicationPreference(1, guest.Id, communicationTypes.First().Id);
context.SaveChanges();
The "guest" is not relate or not in work context of your "Context" instance so guest never save. I hope you get it.
I am getting the "Invalid column name" error and I strongly believe its because my mapping is wrong.
I am using C# and database first.
My tables are as follow:
icotb001_unidades_c ---- gedtbd042_posto_atendimento_c ------ gedtbd039_posto_atendimento_m
(id)nu_unidade ------------ (id)nu_unidade ------------------------------ (id)co_posto
no_unidade----------------- (fk)co_posto---------------------------------- no_posto
Trying to make it clear:
icotb001_unidades_c-- 0..1:1 -- gedtbd042_posto_atendimento_c -- M:1 -- gedtbd039_posto_atendimento_m
gedtbd042_posto_atendimento_c is inheriting from icotb001_unidades_c. That's why it's not a typcal on-to-many relatioship.
Using database first, the table gedtbd042_posto_atendimento_c was not created and the other tables has the following code:
public partial class icotb001_unidades_c
{
public icotb001_unidades_c ()
{
}
[Key]
public string nu_unidade { get; set; }
public string no_unidade{ get; set; }
public virtual gedtbd039_posto_atendimento_m gedtbd039_posto_atendimento_m { get; set; }
}
public partial class gedtbd039_posto_atendimento_m
{
public gedtbd039_posto_atendimento_m()
{
icotb001_unidades_c = new HashSet<icotb001_unidades_c>();
}
[Key]
[StringLength(9)]
public string co_posto { get; set; }
[Required]
public string no_posto { get; set; }
public virtual ICollection<icotb001_unidades_c> icotb001_unidades_c { get; set; }
}
It wasn't created any fluent API between then either. I searched MSDN and this answered question, but couldn't get it working.
Any ideas?
EDIT
I changed the above table names to make it clear with the table statements below.
CREATE TABLE [dbo].[gedtbd039_posto_atendimento_m](
[co_posto] [char](9) NOT NULL,
[no_posto] [varchar](100) NOT NULL,
CONSTRAINT [PK_gedtbd039_posto_atendimento] PRIMARY KEY CLUSTERED
(
[co_posto] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 98) ON [PRIMARY]
) ON [PRIMARY]
---------
CREATE TABLE [dbo].[icotb001_unidades_c](
[nu_unidade] [char](4) NOT NULL,
[no_unidade] [varchar](70) NOT NULL,
CONSTRAINT [PK_icotb001_unidades_c] PRIMARY KEY CLUSTERED
(
[nu_unidade] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 98) ON [PRIMARY]
) ON [PRIMARY]
---------
CREATE TABLE [dbo].[gedtbd042_posto_atendimento_c](
[co_posto] [char](9) NOT NULL,
[nu_unidade] [char](4) NOT NULL,
CONSTRAINT [PK_gedtbd042_vinculacao_posto_atendimento] PRIMARY KEY CLUSTERED
(
[nu_unidade] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 98) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[gedtbd042_posto_atendimento_c] WITH CHECK ADD CONSTRAINT [FK_gedtbd042_vinculacao_posto_atendimento_gedtbd039_posto_atendimento] FOREIGN KEY([co_posto])
REFERENCES [dbo].[gedtbd039_posto_atendimento_m] ([co_posto])
GO
ALTER TABLE [dbo].[gedtbd042_posto_atendimento_c] CHECK CONSTRAINT [FK_gedtbd042_vinculacao_posto_atendimento_gedtbd039_posto_atendimento]
GO
ALTER TABLE [dbo].[gedtbd042_posto_atendimento_c] WITH CHECK ADD CONSTRAINT [FK_gedtbd042_vinculacao_posto_atendimento_icotb001_unidades_c] FOREIGN KEY([nu_unidade])
REFERENCES [dbo].[icotb001_unidades_c] ([nu_unidade])
GO
ALTER TABLE [dbo].[gedtbd042_posto_atendimento_c] CHECK CONSTRAINT [FK_gedtbd042_vinculacao_posto_atendimento_icotb001_unidades_c]
GO
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.
I have many-to-one mappings working fine, but a one-to-many relationship between locations and location_times keeps giving me an error.
I keep getting this error:
on this line of code:
Mappings look like this:
Location:
public virtual IList<LocationTimes> LocationTimes { get; set; }
public virtual int locationID { get; set; }
public virtual IList<LocationTimes> LocationTimes { get; set; }
public Location()
{
LocationTimes = new List<LocationTimes>();
}
Location Map:
public class LocationMap : ClassMap<Location>
{
public LocationMap()
{
Table("Locations");
Id(x => x.locationID).Column("ID");
HasMany(x => x.LocationTimes)
.Inverse()
.Cascade.All();
Location Table:
CREATE TABLE [dbo].[Locations](
[ID] [int] IDENTITY(1,1) NOT NULL
...
CONSTRAINT [PK_Locations_1] 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]
LocationTimes:
public class LocationTimes
{
public virtual int ID { get; set; }
public virtual Location Location { get; set; }
}
LocationTimesMap:
public class LocationTimesMap : ClassMap<LocationTimes>
{
public LocationTimesMap()
{
Table("Location_Times");
Id(x => x.ID);
References(x => x.Location).Column("LID");
}
}
Location_times table:
CREATE TABLE [dbo].[Location_Times](
[ID] [int] IDENTITY(1,1) NOT NULL,
[LID] [int] NULL,
[EHStart] [int] NULL,
[EHEnd] [int] NULL,
[EHSell] [money] NULL,
CONSTRAINT [PK_Location_Times_1] 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]
The full error message:
"{"could not initialize a collection: [WhygoDomain.Location.LocationTimes#4]
[SQL: SELECT locationti0_.Location_id as Location4_1_, locationti0_.ID as ID1_, locationti0_.ID as ID1_0_, locationti0_.LID as LID1_0_, locationti0_.EHStart as EHStart1_0_
FROM Location_Times locationti0_
WHERE locationti0_.Location_id=?]"}"
I can see from the sql in the error message that it is indeed looking for locationti0_.Location_id, which I know doesn't exist. I don't know why it's looking for that though.
This is usually a problem of ID name mis-matches on your tables. Check to ensure that Location has an ID column on the table and that it follows your convention or is mapped correctly. You don't share Location's map, full object graph, or any of the tables so its hard to tell what the IDs are named and if they are matching up correctly.
Edit:
Per RichardD's answer in the comments, modify the LocationMap to be as follows:
public class LocationMap : ClassMap<Location>
{
public LocationMap()
{
Table("Locations");
Id(x => x.locationID).Column("ID");
HasMany(x => x.LocationTimes).KeyColumn("LID").Inverse().Cascade.All();