I am connecting to a legacy sqlserver database. One of the tables has column name "Primary". The scripts are failing due to that.
Script generated by nhibernate:
SELECT locations0_.CustomerID as CustomerID1_, locations0_.LocationID as LocationID1_, locations0_.LocationID as LocationID2_0_, locations0_.Primary as Primary2_0_,locations0_.CustomerID as CustomerID2_0_
FROM dbo.tblLocation locations0_
WHERE locations0_.CustomerID=?
Class:
public class Location
{
public virtual int LocationID { get; set; }
public virtual Customer Customer { get; set; }
public virtual int? CustomerID { get; set; }
public virtual string LocationName { get; set; }
public virtual string Address1 { get; set; }
public virtual string Address2 { get; set; }
public virtual string Address3 { get; set; }
public virtual string City { get; set; }
public virtual string StateOrProvince { get; set; }
public virtual string PostalCode { get; set; }
public virtual datetime? LTimeStamp{ get;set; }
public virtual bool Primary { get; set; }
}
Map:
public class TblLocationMap : ClassMap
{
public TblLocationMap()
{
Table("tblLocation");
//LazyLoad();
Id(x => x.LocationID).GeneratedBy.Identity().Column("LocationID");
References(x => x.Customer).Column("CustomerID");
Map(x => x.LocationName).Column("LocationName").Length(50);
Map(x => x.Address1).Column("Address1").Length(200);
Map(x => x.Address2).Column("Address2").Length(200);
Map(x => x.Address3).Column("Address3").Length(200);
Map(x => x.City).Column("City").Length(100);
Map(x => x.StateOrProvince).Column("StateOrProvince").Length(100);
Map(x => x.PostalCode).Column("PostalCode").Length(20);
//Map(x => x.Primary).Column("Primary").Not.Nullable();
//Map(x => x.LTimestamp).Column("LTimestamp");
HasMany(x => x.Contacts).KeyColumn("LocationID");
}
sql:
CREATE TABLE [dbo].[tblLocation]
(
[LocationID] [int] IDENTITY(1,1) NOT NULL,
[CustomerID] [int] NULL,
[LocationName] nvarchar NULL,
[Address1] nvarchar NULL,
[Address2] nvarchar NULL,
[Address3] nvarchar NULL,
[City] nvarchar NULL,
[StateOrProvince] nvarchar NULL,
[PostalCode] nvarchar NULL,
[Primary] [bit] NOT NULL,
[RecTimestamp] [timestamp] NULL,
(
[LocationID] 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
GenericADOException:
could not initialize a collection: [Domain.Locations#466][SQL: SELECT locations0_.CustomerID as CustomerID1_, locations0_.LocationID as LocationID1_, locations0_.LocationID as LocationID2_0_, locations0_.LocationName as Location2_2_0_, locations0_.Address1 as Address3_2_0_, locations0_.Address2 as Address4_2_0_, locations0_.Address3 as Address5_2_0_, locations0_.City as City2_0_, locations0_.StateOrProvince as StateOrP7_2_0_, locations0_.PostalCode as PostalCode2_0_, locations0_.Primary as Primary2_0_, locations0_.CustomerID as CustomerID2_0_ FROM dbo.tblLocation locations0_ WHERE locations0_.CustomerID=?]
Inner exception:
{"Incorrect syntax near the keyword 'Primary'."}
I suspect Primary is a reserved word and is not getting escaped properly, therefore try implicitly escaping the column name with back ticks....
e.g.
Map(x => x.Primary).Column("`Primary`").Not.Nullable();
NHibernate will automatically swap your backtick with square braces if you are using MsSql server [Primary]
Strange that the schema is generating square braces but the select SQL isn't.
Related
I have tried various answers to try and get this fixed. I have tried to do a refresh but with no luck.
All my tables are currently empty. I already have #Html.HiddenFor~ in the view
My controller save action:
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "AdminManager")]
public ActionResult Save(Member member)
{
if (!ModelState.IsValid)
{
var viewModel = new MemberFormViewModel
{
Member = member,
Subjects = _context.Subjects.ToList()
};
return View("MemberForm", viewModel);
}
if (member.Id == 0)
_context.Members.Add(member);
else
{
var memberInDb = _context.Members.Single(m => m.Id == member.Id);
Mapper.Map(memberInDb, member);
}
_context.SaveChanges();
return RedirectToAction("Index", "Member");
}
Specifically the source error shown is:
_context.SaveChanges();
It seems that the code errors when adding a member:
_context.Members.Add(member);
Below is my table code:
CREATE TABLE [dbo].[Members] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (255) NOT NULL,
[DateOfBirth] DATETIME NULL,
[Gender] NVARCHAR (MAX) NULL,
[Email] NVARCHAR (MAX) NOT NULL,
[WorkLocation] NVARCHAR (MAX) NOT NULL,
[Address] NVARCHAR (255) NOT NULL,
[ContactNumber] NVARCHAR (MAX) NOT NULL,
[Biography] NVARCHAR (MAX) NULL,
[MoreInfo] NVARCHAR (MAX) NULL,
[SubjectId] INT NOT NULL,
[ReportId] INT NULL,
CONSTRAINT [PK_dbo.Members] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_dbo.Members_dbo.Reports_ReportId] FOREIGN KEY ([ReportId])
REFERENCES [dbo].[Reports] ([Id]),
CONSTRAINT [FK_dbo.Members_dbo.Subjects_SubjectId] FOREIGN KEY ([SubjectId])
REFERENCES [dbo].[Subjects] ([Id]) ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_SubjectId]
ON [dbo].[Members]([SubjectId] ASC);
GO
CREATE NONCLUSTERED INDEX [IX_ReportId]
ON [dbo].[Members]([ReportId] ASC);
Here is my model that was used for the migration:
public class Member
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
[Display(Name = "Date of birth")]
public DateTime? DateOfBirth { get; set; }
public string Gender { get; set; }
[Required]
public string Email { get; set; }
[Required]
[Display(Name = "Work Location")]
public string WorkLocation { get; set; }
[Required]
[StringLength(255)]
public string Address { get; set; }
[Required]
[Display(Name = "Contact Number")]
public string ContactNumber { get; set; }
public string Biography { get; set; }
[Display(Name = "More Information")]
public string MoreInfo { get; set; }
public Subject Subject { get; set; }
[Required]
[Display(Name = "Subject")]
public int SubjectId { get; set; }
public Report Report { get; set; }
[Key]
[ForeignKey("Report")]
[Display(Name = "Report")]
public int? ReportId { get; set; }
}
I have a base class Person:
[KnownType(typeof(Doctor))]
public abstract class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public DateTime BirthDate { get; set; }
public string Email { get; set; }
public string MobilePhoneNumber { get; set; }
public string HomePhoneNumber { get; set; }
public bool IsGlobal { get; set; }
public bool IsDeleted { get; set; }
public bool IsApproved { get; set; }
public int? FacilityId { get; set; }
public int? AddressId { get; set; }
public virtual FacilityView Facility { get; set; }
public virtual Address Address { get; set; }
public virtual ICollection<Organization> Organizations { get; set; }
public virtual ICollection<TenantEntity> TenantEntities { get; set; }
}
And have nested class Doctor:
public class Doctor : Person
{
public string Speciality { get; set; }
}
Table Person script
CREATE TABLE [core].[Person](
[PersonId] [int] IDENTITY(1,1) NOT NULL,
[Discriminator] [nvarchar](255) NOT NULL,
[FirstName] [nvarchar](255) NOT NULL,
[MiddleName] [nvarchar](255) NULL,
[LastName] [nvarchar](20) NOT NULL,
[Gender] [nvarchar](20) NOT NULL,
[BirthDate] [date] NOT NULL,
[Email] [nvarchar](250) NULL,
[MobilePhoneNumber] [nvarchar](250) NULL,
[HomePhoneNumber] [nvarchar](250) NULL,
[IsGlobal] [bit] NOT NULL,
[IsDeleted] [bit] NOT NULL,
[IsApproved] [bit] NOT NULL,
[FacilityId] [int] NULL,
[AddressId] [int] NULL,
[Speciality] [nvarchar](250) NULL,
And when i try to save new Doctor entity i have an error:
Cannot insert the value NULL into column 'Discriminator'
What i do wrong in this situation?Why EF not save "Doctor" value in Discriminator field?
UPDATE:
part from DBContext:
public DbSet<Person> Persons { get; set; }
#region Person
modelBuilder.Entity<Person>()
.ToTable("Person", "core")
.HasKey(t => t.PersonId);
modelBuilder.Entity<Person>()
.HasOptional(t => t.Facility);
modelBuilder.Entity<Person>()
.HasOptional(t => t.Address);
modelBuilder.Entity<Person>()
.HasMany(x => x.Organizations)
.WithMany()
.Map(x =>
{
x.MapLeftKey("PersonId");
x.MapRightKey("OrganizationId");
x.ToTable("PersonOrganization", "core");
});
modelBuilder.Entity<Person>()
.HasMany(x => x.TenantEntities)
.WithMany()
.Map(x =>
{
x.MapLeftKey("PersonId");
x.MapRightKey("TenantEntityId");
x.ToTable("PersonTenantEntity", "core");
});
#endregion
The default inheritance mapping does not define a discriminator column if only one derived class exists.
Your code will work if you define a second class that derives from Person:
public class Nurse : Person
{
public string Whatever {get;set;}
}
Or add the discriminator explicitly to your model.
modelBuilder.Entity<Doctor>().Map(p => p.Requires("Discriminator").HasValue("Doctor"));
I am trying to map a lookup table to an enum using:
FluentNhibernate 1.3.0.733
NHibernate 3.3.1.4000
I am not able to load objects. If I remove the enum mapping I can load objects.
Code:
Order order = session.Get<Order>(id);
Error:
Provided id of the wrong type. Expected: Order+OrderStatus, got System.Int32
Object:
public class Order
{
public enum OrderStatus
{
PaymentPending = 0
}
public virtual int Id { get; set; }
public virtual Customer Customer { get; set; }
public virtual Address Address { get; set; }
public virtual IList<OrderLine> OrderLines { get; set; }
public virtual OrderStatus Status { get; set; }
public virtual DateTime Created { get; set; }
public Order()
{
OrderLines = new List<OrderLine>();
}
}
Mapping: (I have cut the mapping down to these fields for testing)
public OrderMapping()
{
Table("orders");
Id(x => x.Id);
Id(x => x.Status, "state_id").CustomType<Order.OrderStatus>().Not.Nullable();
References(x => x.Address).Cascade.All().Column("address_id");
References(x => x.Customer).Cascade.All().Column("customer_id");
}
Tables:
CREATE TABLE [order_states] (
[id] INTEGER NOT NULL PRIMARY KEY,
[state] NVARCHAR(50) NOT NULL
);
CREATE TABLE [orders] (
[id] INTEGER NOT NULL PRIMARY KEY,
[customer_id] INTEGER NOT NULL,
[address_id] INTEGER NOT NULL,
[state_id] INTEGER NOT NULL,
[created] DATE,
FOREIGN KEY(customer_id) REFERENCES customers(id),
FOREIGN KEY(address_id) REFERENCES addresses(id),
FOREIGN KEY(state_id) REFERENCES order_states(id)
);
What am I doing wrong?
Caused by a silly error.
I had the the status mapped as an id and not as a property.
Correct mapping:
public OrderMapping()
{
Table("orders");
Id(x => x.Id);
Map(x => x.Status, "state_id").CustomType<Order.OrderStatus>().Not.Nullable();
References(x => x.Address).Cascade.All().Column("address_id");
References(x => x.Customer).Cascade.All().Column("customer_id");
}
What is wrong with my class mappings below?
public class Foo
{
public Foo()
{
ActualCurve = new List<Point>();
TargetCurve = new List<Point>();
}
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Point> ActualCurve { get; set; }
public virtual IList<Point> TargetCurve { get; set; }
}
public class Point
{
public virtual int Id { get; set; }
public virtual double X { get; set; }
public virtual double Y { get; set; }
}
public class FooMapping() : ClassMap<Foo>
{
Table("Foos");
Id(x => x.Id).GeneratedBy.Identity();
Map(x => x.Name).Not.Nullable();
HasMany(x => x.ActualCurve ).Cascade.All();
HasMany(x => x.TargetCurve ).Cascade.All();
}
public class PointMapping() : ClassMap<Point>
{
Table("Points");
Not.LazyLoad();
Id(x => x.Id).GeneratedBy.Identity();
Map(x => x.X).Not.Nullable();
Map(x => x.Y).Not.Nullable();
}
These mappings produce
CREATE TABLE [dbo].[Foos](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar] NOT NULL,
[RecipeRevisionId] [int] NOT NULL
CREATE TABLE [dbo].[Points](
[Id] [int] IDENTITY(1,1) NOT NULL,
[X] [float] NOT NULL,
[Y] [float] NOT NULL,
[FooId] [int] NOT NULL
Essentially, the problem is that when I am pulling a persisted Foo object back out of the database, the Foo.ActualCurve and Foo.TargetCurve lists both get populated with the combined contents of both lists. There clearly isn't a column that keys which set of points belong to the correct curve within Foo, but I am not sure how to change the mapping to maintain the two distinct sets of Points.
I think you will need to specify a separate column for the references:
HasMany(x => x.ActualCurve ).Cascade.All().KeyColumn("ActualCurveId");
HasMany(x => x.TargetCurve ).Cascade.All().KeyColumn("TargetCurveId");
EDIT: Column->KeyColumn
I have following entities
public class Entity1
{
public virtual Guid Id { get; set; }
public virtual IDictionary<Guid, Entity2> Entities2 { get; set; }
}
public class Entity2
{
public virtual Guid Id { get; set; }
public virtual IDictionary<Guid, Entity1> Entities1 { get; set; }
}
DB table
CREATE TABLE [dbo].[EntityLinks](
[Entity1Id] [uniqueidentifier] NOT NULL,
[Entity2Id] [uniqueidentifier] NOT NULL,
[LinkItemId] [uniqueidentifier] NOT NULL
)
and following mappings:
for Entity1
mapping.HasManyToMany<Entity2>(rc => rc.Entities2)
.Table("EntityLinks")
.ParentKeyColumn("Entity1Id")
.ChildKeyColumn("Entity2Id")
.AsMap<Guid>("LinkItemId")
for Entity2
mapping.HasManyToMany<Entity1>(rc => rc.Entities1)
.Table("EntityLinks")
.ParentKeyColumn("Entity2Id")
.ChildKeyColumn("Entity1Id")
.AsMap<Guid>("LinkItemId")
adding data works fine and I can get and see Entity1.Entities2 populated but Entity2.Entities1 is not populated.
Any suggestions why this might be?
Thank you in advance.
I'm probably wrong but you can try:
mapping.HasManyToMany<Entity2>(rc => rc.Entities2)
.Table("EntityLinks")
.ParentKeyColumn("Entity1Id")
.ChildKeyColumn("Entity2Id")
.AsMap<Guid>("LinkItemId")
.Inverse()
and
mapping.HasManyToMany<Entity1>(rc => rc.Entities1)
.Table("EntityLinks")
.ParentKeyColumn("Entity2Id")
.ChildKeyColumn("Entity1Id")
.AsMap<Guid>("LinkItemId")
.Cascade.All();