I am new to c# and NHibernate so please forgive me if this question is out of line.
I am working on mapping a table in Nhibernate by code i keep getting this error:
could not execute query
I have creates following classes
class PoliceData
{
virtual public int policyNumber { get; set; }
virtual public String product { get; set; }
virtual public String Navn { get; set; }
virtual public String Adresse { get; set; }
virtual public String Husnr { get; set; }
virtual public String Postnr { get; set; }
virtual public String By { get; set; }
virtual public String Lattitude { get; set; }
virtual public String Longitude { get; set; }
virtual public String Cell100M { get; set; }
virtual public String Cell1KM { get; set; }
virtual public String Cell10KM { get; set; }
}
class PoliceDataMap : ClassMapping<PoliceData>
{
public PoliceDataMap()
{
Table("policeDataView");
Lazy(true);
Property(x => x.policyNumber, map => map.NotNullable(true));
Property(x => x.product, map => map.NotNullable(true));
Property(x => x.Navn, map => map.NotNullable(true));
Property(x => x.Adresse, map => map.NotNullable(true));
Property(x => x.Husnr, map => map.NotNullable(true));
Property(x => x.Postnr, map => map.NotNullable(true));
Property(x => x.By, map => map.NotNullable(true));
Property(x => x.Lattitude, map => map.NotNullable(true));
Property(x => x.Longitude, map => map.NotNullable(true));
Property(x => x.Cell100M, map => map.NotNullable(true));
Property(x => x.Cell1KM, map => map.NotNullable(true));
Property(x => x.Cell10KM, map => map.NotNullable(true));
}
}
I'm running the following query
public DbFactory()
{
using (ISession session = OpenSession())
{
IList<PoliceData> policedata = session.Query<PoliceData>().Where(p => p.policyNumber == 053126703).ToList();
//IList<Pet> pets = query.List<Pet>();
// Console.Out.WriteLine("pets.Count = " + pets.Count);
// pets.ToList().ForEach(p => Console.WriteLine(p.PetName));
// Console.Read();
}
}
It ends in exception with the following message
could not execute query:
[ select policedata0_.id as id0_, policedata0_.policyNumber as policyNu2_0_, policedata0_.product as product0_, policedata0_.Navn as Navn0_, policedata0_.Adresse as Adresse0_, policedata0_.Husnr as Husnr0_, policedata0_.Postnr as Postnr0_, policedata0_.Bynavn as Bynavn0_, policedata0_.Lattitude as Lattitude0_, policedata0_.Longitude as Longitude0_, policedata0_.Cell100M as Cell11_0_, policedata0_.Cell1KM as Cell12_0_, policedata0_.Cell10KM as Cell13_0_ from policeDataView policedata0_ where policedata0_.policyNumber=#p0 ]
It seems to me that NhiberNate want a Id column even though there are none in the table.
So i did try to create a Id in the code by adding this to class PoliceData
virtual public int Id { get; set; }
and adding this to PoliceDataMap
Id(x => x.id, map => map.Generator(Generators.Identity));
Now im getting compile error:
the name 'map' does not exits in the current context
What could I do to solve this, Does NHibernate need a column defined in the map class by
map.Generator(Generators.Identity));
What does it do ?
Any mapped entity must have mapped ID, so you have to provide some. But in case that you have ID like this:
virtual public int Id { get; set; }
Mapping should be
//Id(x => x.id, map => map.Generator(Generators.Identity));
Id(x => x.Id, map => map.Generator(Generators.Identity));
Also check the
Mapping-by-Code - Id, NaturalId
snippet how to mapp ID:
Id(x => x.Id, m =>
{
m.Column("id");
m.Generator(Generators.Native, g => g.Params(new
{
// generator-specific options
}));
m.Length(10);
m.Type(new Int32Type());
m.Access(Accessor.Field);
});
Related
I'm new to C# / .NET Core and I'm trying to create a Web API. I have 2 models; Community & Rank
Community:
public class Community
{
public long Id { get; set; }
public long FrontId { get; set; }
public string Name { get; set; }
[ForeignKey("CommunityId")]
public virtual ICollection<Rank> Ranks { get; set; }
}
Rank:
public class Rank
{
public long Id { get; set; }
public long CommunityId { get; set; } [Required]
public string Name { get; set; } [Required]
public string Prefix { get; set; }
public virtual Community Community { get; set; }
}
I have my context set up like so:
public class CommunityContext : DbContext
{
public DbSet<Community> Communities { get; set; }
public DbSet<Rank> Ranks { get; set; }
public CommunityContext(DbContextOptions<CommunityContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
//Communities
builder.Entity<Community>(entity =>
{
entity.HasKey(c => c.Id);
entity.Property(c => c.Name).IsRequired();
entity.Property(c => c.FrontId).IsRequired();
// entity.Property(c => c.Ranks).IsRequired(false);
entity.HasMany(c => c.Ranks).WithOne().HasForeignKey(c => c.CommunityId).IsRequired();
});
//Ranks
builder.Entity<Rank>(entity =>
{
entity.HasKey(r => r.Id);
entity.Property(r => r.Name).IsRequired();
entity.Property(r => r.Prefix).IsRequired();
entity.Property(r => r.CommunityId).HasColumnName("CommunityId").IsRequired();
// entity.HasOne(r => r.Community).WithMany(s => s.Ranks);
});
}
}
I've done my database migrations etc, and when creating new entries, all works as expected currently, however trying to GET either communities or ranks returns the error:
MySql.Data.MySqlClient.MySqlException (0x80004005): Unknown column 'r.CommunityId1' in 'field list'
Any suggestions would be appreciated!
Thanks
Your Configurations should be like this:
...
//Communities
builder.Entity<Community>(entity =>
{
builder.ToTable("Community");
builder.HasKey(c => c.Id);
builder.Property(c => c.Id).HasColumnName("CommunityId").ValueGeneratedOnAdd();
entity.Property(c => c.Name).IsRequired();
entity.Property(c => c.FrontId).IsRequired();
// entity.Property(c => c.Ranks).IsRequired(false);
entity.HasMany(c => c.Ranks).WithOne().HasForeignKey(c => c.CommunityId).IsRequired();
});
//Ranks
builder.Entity<Rank>(entity =>
{
builder.ToTable("Rank");
builder.HasKey(r => r.Id);
builder.Property(r => r.Id).HasColumnName("RankId").ValueGeneratedOnAdd();
entity.Property(r => r.Name).IsRequired();
entity.Property(r => r.Prefix).IsRequired();
entity.Property(r => r.CommunityId).HasColumnName("CommunityId").IsRequired();
// entity.HasOne(r => r.Community).WithMany(s => s.Ranks);
});
...
i am developing an API which returns records about representatives, everything works fine, i am getting the desired results, the problem starts when i want to sort by a related entity.
I am using Entity Framework to link the tables.
The following is a snippet of the DB diagram related to my piece of work.
I would like to order by Level in Tier table.
The following is my current working code:
var profiles = _context.Profile
.OrderBy(p => p.Person.FirstName)
.Include(p => p.Person)
.Include(p => p.Person.Address)
.Include(p => p.Person.Representative.RepresentativeTierHistory)
.ThenInclude(r => r.Tier)
.Skip(start)
.Take(limit);
var mappedProfiles = _mapper.Map<List<ShortLeaderProfile>>(profiles);
If someone could guide me on how to order the results by Tier.Level i would be really thankful. I have tried the following and it does not work..
Attempt:
.OrderBy(p => p.Person.Representative.RepresentativeTierHistory.OrderByDescending(t => t.Tier.Level))
This is my Mapping Code:
public ProfilesProfile()
{
MapAddressToLeaderProfile();
}
private void MapAddressToLeaderProfile()
{
CreateMap<Models.DataModels.Profile, ShortLeaderProfile>()
.ForMember(lp => lp.Id, opt => opt.MapFrom(p => p.Person.Id))
.ForMember(lp => lp.FirstName, opt => opt.MapFrom(p => p.Person.FirstName))
.ForMember(lp => lp.LastName, opt => opt.MapFrom(p => p.Person.LastName))
.ForMember(lp => lp.PreviousOccupation, opt => opt.MapFrom(p => p.PreviousOccupation))
.ForMember(lp => lp.Code,
opt => opt.MapFrom(p =>
ActiveTier(p.Person.Representative.RepresentativeTierHistory, DateTime.Now.Date)))
.ForMember(lp => lp.location, spt => spt.MapFrom(l => l));
CreateMap<Models.DataModels.Profile, Location>()
.ForMember(lp => lp.Name, opt => opt.MapFrom(p => p.Person.Address.AddressCityOrTown))
.ForMember(lp => lp.Latitude, opt => opt.MapFrom(p => p.Latitude))
.ForMember(lp => lp.Longitude, opt => opt.MapFrom(p => p.Longitude));
}
public static string ActiveTier(IEnumerable<RepresentativeTierHistory> representativeTierHistories, DateTime now) =>
representativeTierHistories?
.SingleOrDefault(x => x.StartDate <= now && x.EndDate > now)?
.Tier?
.Code;
}
This is my Profile Entity Class:
[Table(nameof(Profile), Schema = "common")]
[ExcludeFromCodeCoverage]
public class Profile
{
public int Id { get; set; }
public string PreviousOccupation { get; set; }
public string ShortDescription { get; set; }
public string LongDescription { get; set; }
[Column(TypeName = "numeric(10, 6)")]
public decimal? Longitude { get; set; }
[Column(TypeName = "numeric(10, 6)")]
public decimal? Latitude { get; set; }
public int DisplayOrder { get; set; }
public int PersonId { get; set; }
[ForeignKey(nameof(PersonId))]
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime RecordStartDateTime { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime RecordEndDatetime { get; set; }
public List<ProfileSocialMedia> ProfileSocialMedias { get; set; }
public Person Person { get; set; }
My Class Model:
public class ShortLeaderProfile
{
public int Id;
public string FirstName;
public string LastName;
public string PreviousOccupation;
[CanBeNull] public string Code;
[CanBeNull] public Location location;
}
.OrderBy(p => p.Person.Representative.RepresentativeTierHistory.Max(t => t.Tier.Level))
I saw many exemple on the internet on Mapping relation object with nhibernate but i can't make mine works.
I have two Model for exemple:
public class Vehicule
{
public virtual int Id { get; set; }
public virtual int Brand { get; set; }
public virtual int Color { get; set; }
public virtual int UserID { get; set; }
public virtual UserModel User { get; set; }
}
public class VehiculeMap: ClassMapping<Vehicule>
{
public VehiculeMap()
{
Table("G1Vehicule");
Id(x => x.Id, map => { map.Column("id"); });
Property(x => x.Brand, map => { map.Column("brand"); });
Property(x => x.Color, map => { map.Column("color"); });
Property(x => x.UserID, map => { map.Column("user_id"); });
}
}
public class UserModel
{
public virtual int Id { get; set; }
public virtual int Username { get; set; }
}
public class UserModelMap : ClassMapping<UserModel>
{
public UserModelMap()
{
Table("Users");
Id(x => x.Id, map => { map.Column("id"); });
Property(x => x.Username, map => { map.Column("username"); });
}
}
Previously, I only displayed the UserId, but now I would like to fill my UserModel when I get a specific VehiculeModel from the database.
Here my Model relation is OneToOne.
Also for design purpose I will never query an User to get his list of vehicule, so I dont need to have a "List of VehiculeModel" in my UserModel.
If you have any hint, about how I can map this in my Map class (saw a lots of xml mapping but i would like to map it by code) It would be very appreciated.
Thanks
I finally made it work.
nothing to complicate in fact, I just forgot to add my second model (UserModelMap) in the map class list for Nhibernate.
public class VehiculeMap: ClassMapping<Vehicule>
{
public VehiculeMap()
{
Table("G1Vehicule");
Id(x => x.Id, map => { map.Column("id"); });
Property(x => x.Brand, map => { map.Column("brand"); });
Property(x => x.Color, map => { map.Column("color"); });
Property(x => x.UserID, map => { map.Column("user_id"); });
ManyToOne(x => x.User, map => {
map.Column("user_id"),
map.Fetch(FetchKind.Join),
map.notFound(NotFoundMode.Ignore)
})
}
}
Maybe it could help someone else.
For a metaphor here, a person can have zero or one car, and one car belongs only to one person.
I have a database that looks like this:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Car Car { get; set; }
}
public class Car
{
public int PersonId { get; set; }
public virtual Person Person { get; set; }
public string Model { get; set; }
}
I want to have a link from the person to its car, if existent, and from the car to its person. So my EntityTypeConfigurations are like so:
public class PersonConfig : EntityTypeConfiguration<Person>
{
public PersonConfig()
{
ToTable("tblPerson");
HasKey(s => s.Id)
.Property(s => s.Id)
.HasColumnName("idPerson");
Property(s => s.Name)
.HasColumnName("strName")
.IsRequired();
HasOptional(a => a.Car)
.WithOptionalPrincipal();
}
}
public class CarConfig : EntityTypeConfiguration<Car>
{
public CarConfig()
{
ToTable("tblCar");
HasKey(s => s.PersonId)
.Property(s => s.PersonId)
.HasColumnName("idPerson");
Property(s => s.Model)
.HasColumnName("strModel")
.IsRequired();
HasRequired(a => a.Person)
.WithRequiredDependent();
}
}
I don't know what I'm getting wrong, but EF:
Creates an additional Person_Id field in tblCar
Creates two foreign keys in tblCar, one named idPerson and the other Person_Id
What am I forgetting or doing wrong?
You have to use WithRequired instead of WithOptionalPrincipal, and the relationship do not need to be configured in both sides.
public class PersonConfig : EntityTypeConfiguration<Person>
{
public TaskConfig()
{
ToTable("tblPerson");
HasKey(s => s.Id);
Property(s => s.Id)
.HasColumnName("idPerson");
Property(s => s.Name)
.HasColumnName("strName")
.IsRequired();
HasOptional(a => a.Car)
.WithRequired(s => s.Person);
}
}
public class CarConfig : EntityTypeConfiguration<Car>
{
public CarConfig()
{
ToTable("tblCar");
HasKey(s => s.PersonId)
.Property(s => s.PersonId)
.HasColumnName("idPerson");
Property(s => s.Model)
.HasColumnName("strModel")
.IsRequired();
//not necessary
//HasRequired(a => a.Person)
//.WithRequiredDependent();
}
}
What am I forgetting or doing wrong?
You are not configuring the Person - Car relationship correctly.
Let fix that. Note that you don't need to configure the relationship in both places.
Remove the following from the Person config:
HasOptional(a => a.Car)
.WithOptionalPrincipal();
and replace the following in the Car config:
HasRequired(a => a.Person)
.WithRequiredDependent();
with
HasRequired(c => c.Person)
.WithOptional(p => p.Car);
I have a table in the database that is used only for holding some ID's descriptions:
TABLE SomeClass
- Columns
- ClassTypeID INT CONSTRAINT etc
TABLE SomeClassTypes
- ClassTypeID INT IDENTITY
- Description NVARCHAR
It's done like this so it's easy for users to insert/remove new types.
I want to get a report of all of SomeClass, but I'd like to have a string property to hold the description from the other table:
public class SomeClass
{
public virtual int SomeClassID { get; set; }
public virtual int ClassTypeID { get; set; }
public virtual string DescriptionType { get; set; }
}
public class SomeClassMap : ClassMapping<SomeClass>
{
public SomeClassMap()
{
Table("SomeClassTable");
Property(p => p.SomeClassID, map =>
{
map.Column("SomeClassID");
map.Generator(Generators.Identity);
});
Property(p => p.ClassTypeID, map => map.Column("ClassTypeID"));
//Other properties here
Property(p => p.DescriptionType, ?); //This line
}
}
How can I do this?
Try to use joined table.
public class SomeClassMap : ClassMapping<SomeClass>
{
public SomeClassMap()
{
Table("SomeClassTable");
Property(p => p.SomeClassID, map =>
{
map.Column("SomeClassID");
map.Generator(Generators.Identity);
});
Property(p => p.ClassTypeID, map => map.Column("ClassTypeID"));
//Other properties here
Join("SomeClassTypes", m =>
{
m.KeyColumn("ClassTypeId");
m.Fetch.Join();
m.Map(x => x.DescriptionType).Column("Description");
})
}
}
EDITED
If you use fluent mapping built in NHibernate, try this:
public class SomeClassMap : ClassMapping<SomeClass>
{
public SomeClassMap()
{
Table("SomeClassTable");
Property(p => p.SomeClassID, map =>
{
map.Column("SomeClassID");
map.Generator(Generators.Identity);
});
Property(p => p.ClassTypeID, map => map.Column("ClassTypeID"));
//Other properties here
Property(p => p.DescriptionType, ?); //This line
Join("SomeClassTypes", m =>
{
m.Key(k => k.Column("ClassTypeId"));
m.Fetch(FetchKind.Join);
m.Property(x => x.DescriptionType).Column("Description");
});
}
}