Fluent Nhibernate mapping help - c#

Domain:
public class Account
{
public virtual int AccountId { get; set; }
public virtual int UserId { get; set; }
public virtual string HostName { get; set; }
public virtual DateTime CreatedOn { get; set; }
public virtual bool Deleted { get; set; }
}
public class Person
{
public Person()
{
PersonRoles = new List<PersonRole>();
}
public virtual int PersonId { get; set; }
public virtual Guid PersonGuid { get; set; }
public virtual string FirstName { get; set; }
public virtual string Surname { get; set; }
public virtual string Email { get; set; }
public virtual string Password { get; set; }
public virtual string SaltKey { get; set; }
public virtual int PersonType { get; set; }
public virtual DateTime CreatedOn { get; set; }
public virtual bool Deleted { get; set; }
public virtual bool Active { get; set; }
public virtual int? AccountId { get; set; }
public virtual ICollection<PersonRole> PersonRoles { get; private set; }
public virtual Account Account { get; set; }
}
Mapping:
public AccountMap()
{
Id(x => x.AccountId, "AccountId").Column("AccountId");
Map(x => x.UserId);
Map(x => x.HostName);
Map(x => x.CreatedOn);
Map(x => x.Deleted);
Table("crm_accounts");
}
public PersonMap()
{
Id(x => x.PersonId).Column("PersonId");
Map(x => x.PersonGuid);
Map(x => x.FirstName);
Map(x => x.Surname);
Map(x => x.Email);
Map(x => x.Password);
Map(x => x.SaltKey);
Map(x => x.PersonType);
Map(x => x.CreatedOn);
Map(x => x.Deleted);
Map(x => x.Active);
HasManyToMany<PersonRole>(x => x.PersonRoles)
.ParentKeyColumn("RoleId")
.ChildKeyColumn("PersonId")
.Cascade.All()
.Table("crm_people_roles_mapping");
//Map(x => x.AccountId);
References(x => x.Account, "AccountId").Column("AccountId");
Table("crm_people");
}
Issue:
When saving a new person with an account id everything saves OK except for the acccount id field.
A person doesn't need to have an account to exist.
What am I doing wrong?
Thanks.

HNibernate doesn't know what to do with your AccountId. On your person object, you've got an Account and an AccountId property. I'll bet if you assigned the Account to the person before you save it, it'd all start working.
Get rid of that AccountId property. You don't need it.

Related

How to map a unidirectional many-to-one relationship?

I have an Item entity:
public class Item
{
public long Id { get; set; }
public string Name { get; set; }
public string Skuid { get; set; }
public double Price { get; set; }
public double Amount { get; set; }
}
And an Order entity:
public class Order
{
public long Id { get; set; }
public DateTime Date { get; set; }
public StatusEnum Status { get; set; }
public long SellerId { get; set; }
public Seller Seller { get; set; }
public double Total { get; set; }
public IList<Item> Items { get; set; }
}
My objective is to save the Order containing the items in the Database, but when the request is made, only the reference of my entity "Seller" is saved, but not the references of the items.
I did the following mapping on the "Order" entity:
public class OrderMap : IEntityTypeConfiguration<Order>
{
public void Configure(EntityTypeBuilder<Order> builder)
{
builder.ToTable("Orders");
builder.HasKey(x => x.Id);
builder.Property(x => x.Id)
.ValueGeneratedOnAdd()
.UseIdentityColumn();
builder.Property(x => x.Date)
.IsRequired()
.HasColumnName("DateSale")
.HasColumnType("DATETIME")
.HasDefaultValueSql("GETDATE()");
builder.Property(x => x.Total)
.IsRequired()
.HasColumnName("Total")
.HasColumnType("DECIMAL");
builder.Property(x => x.Status)
.IsRequired()
.HasConversion(
v => v.ToString(),
v => (StatusEnum)Enum.Parse(typeof(StatusEnum), v))
.HasColumnName("Status")
.HasColumnType("NVARCHAR") //verificar se nao vai dar conflito
.HasMaxLength(120);
builder
.HasOne(x => x.Seller)
.WithOne()
.HasConstraintName("FK_Seller_Order")
.OnDelete(DeleteBehavior.Cascade);
builder
.HasMany(x => x.Items)
.WithOne()
.HasConstraintName("FK_Item_Order")
.IsRequired()
.OnDelete(DeleteBehavior.Cascade); //
}
}
What is the correct mapping to do?
Please first add these properties OrderId and Order to your Item entity class. This way you are instructions the framework to create an OrderId foreign key
column in the database.
public class Item
{
public long Id { get; set; }
public string Name { get; set; }
public string Skuid { get; set; }
public double Price { get; set; }
public double Amount { get; set; }
public long OrderId { get; set; }
public Order Order {get; set; }
}
And perhaps this part
builder.HasMany(x => x.Items).WithOne()
should be like this
builder.HasMany(x => x.Items).WithOne(x => x.Order)

Fluent NHibernate foreign key is null

I have two tables - master-detail with relation one-to-many.
Here are definitions and mappings:
public class Employee
{
public virtual int Id { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual IList<Project> Projects { get; set; }
public Employee()
{
Projects = new List<Project>();
}
}
public class Project
{
public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
public virtual double EstimatedHours { get; set; }
public virtual Employee Employee { get; set; }
}
public EmployeeMap()
{
Id(x => x.Id);
Map(x => x.FirstName);
Map(x => x.LastName);
HasMany<Project>(x => x.Projects)
.KeyColumn("Id_emp")
.Cascade.All()
.Inverse()
.LazyLoad();
}
public ProjectMap()
{
Id(x => x.Id);
Map(x => x.Name);
Map(x => x.EstimatedHours);
References(x => x.Employee).Class<Employee>().Columns("Id_emp").ForeignKey();
}
When I save data both employee and project tables are filled with data but in project table field Id_emp is null instead to have Id of employee.
What am I missing in mappings and referencing?

AutoMapper Update UseDestinationValue Not Working as expected on Virtual Properties

Struggling to get AutoMapper (6.1.1) to work in this scenario of attempting to update an existing Vendor and associated Vendor Contacts.
I've tried using .ignore() and .UseDestinationValues() on the related entities, both to no avail.
Here's what happens to the destination values after the map:
existingStratusVendor.Id = 0 (should be value of existing)
existingStratusVendor.VendorContacts.Id = 0 (should be value of existing)
existingStratusVendor.Items = null, but had 1 related entity prior to mapping, same with all other related virtual properties. (this happens for all other virtual properties that I've marked as .UseDestinationValues() as well)
What am I doing wrong or am I misunderstanding how this is supposed to work?
POCOs
public partial class Vendor
{
public Vendor()
{
this.Items = new HashSet<Item>();
this.Items1 = new HashSet<Item>();
this.VendorContacts = new HashSet<VendorContact>();
this.POHeaders = new HashSet<POHeader>();
this.ReceiptHeaders = new HashSet<ReceiptHeader>();
this.ItemPriceCostRules = new HashSet<ItemPriceCostRule>();
}
public int Id { get; set; }
public int CompanyId { get; set; }
public string VendorName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Notes { get; set; }
public int CreatedById { get; set; }
public System.DateTime CreatedOn { get; set; }
public int ModifiedById { get; set; }
public System.DateTime ModifiedOn { get; set; }
public string FinancialsId { get; set; }
public int LeadTimeDays { get; set; }
public int SafetyStockDays { get; set; }
public virtual ICollection<Item> Items { get; set; }
public virtual ICollection<Item> Items1 { get; set; }
public virtual ICollection<VendorContact> VendorContacts { get; set; }
public virtual ICollection<POHeader> POHeaders { get; set; }
public virtual Company Company { get; set; }
public virtual UserProfile UserProfile { get; set; }
public virtual UserProfile UserProfile1 { get; set; }
public virtual ICollection<ReceiptHeader> ReceiptHeaders { get; set; }
public virtual ICollection<ItemPriceCostRule> ItemPriceCostRules { get; set; }
}
public partial class VendorContact
{
public int Id { get; set; }
public int VendorId { get; set; }
public string ContactName { get; set; }
public string EmailAddress { get; set; }
public string OfficePhone { get; set; }
public string CellPhone { get; set; }
public int CreatedById { get; set; }
public System.DateTime CreatedOn { get; set; }
public int ModifiedById { get; set; }
public System.DateTime ModifiedOn { get; set; }
public bool PurchasingContact { get; set; }
public virtual Vendor Vendor { get; set; }
public virtual UserProfile UserProfile { get; set; }
public virtual UserProfile UserProfile1 { get; set; }
}
Maps
CreateMap<Vendor, Vendor>()
.ForMember(dest => dest.Id, option => option.UseDestinationValue())
.ForMember(dest => dest.Company, option => option.UseDestinationValue())
.ForMember(dest => dest.POHeaders, option => option.UseDestinationValue())
.ForMember(dest => dest.ReceiptHeaders, option => option.UseDestinationValue())
.ForMember(dest => dest.Items, option => option.UseDestinationValue())
.ForMember(dest => dest.Items1, option => option.UseDestinationValue())
.ForMember(dest => dest.ItemPriceCostRules, option => option.UseDestinationValue())
.ForMember(dest => dest.UserProfile, option => option.UseDestinationValue())
.ForMember(dest => dest.UserProfile1, option => option.UseDestinationValue())
;
CreateMap<VendorContact, VendorContact>()
.ForMember(dest => dest.Id, option => option.UseDestinationValue())
.ForMember(dest => dest.VendorId, option => option.UseDestinationValue())
.ForMember(dest => dest.UserProfile, option => option.UseDestinationValue())
.ForMember(dest => dest.UserProfile1, option => option.UseDestinationValue())
Code
public ActionConfirmation<int> ImportFromFinancials(Vendor financialsModifiedVendor, int intUserId)
{
Vendor vendorToUpdate;
var existingStratusVendor = _vendorRepository
.SearchFor(a => a.CompanyId == intCompanyId && a.FinancialsId == financialsModifiedVendor.FinancialsId).FirstOrDefault();
if (existingStratusVendor == null) //add a new vendor
{
vendorToUpdate = financialsModifiedVendor;
}
else
{
Mapper.Map(financialsModifiedVendor, existingStratusVendor);
vendorToUpdate = existingStratusVendor;
}
//Save Vendor
var baseAppServ = new BaseAppServ<Vendor>(_repository);
var vendorUpdateResult = baseAppServ.SaveOrUpdate(vendorToUpdate, intUserId);
if (!vendorUpdateResult.WasSuccessful) return vendorUpdateResult;
...
}
both entities has the same name, it looks like you are missing a namespace
CreateMap<Other.Namespace.VendorContact, VendorContact>()
.ForMember(dest => dest.Id, option => option.UseDestinationValue())
.ForMember(dest => dest.VendorId, option => option.UseDestinationValue())
.ForMember(dest => dest.UserProfile, option => option.UseDestinationValue())
.ForMember(dest => dest.UserProfile1, option => option.UseDestinationValue())

Removing entity when entity splitting used

I'm building Reporting system, but having problem with removing data from db.
public class Report
{
[Key]
public int ReportId { get; set; }
public string Title { get; set; }
public int? DateRange { get; set; }
public int Layout { get; set; }
public DateTime? DateFrom { get; set; }
public DateTime? DateTo { get; set; }
public int OwnerId { get; set; }
public DateTime DateCreated { get; set; }
public bool Active { get; set; }
public virtual List<ReportCharts> ReportCharts { get; set; }
public virtual List<ReportElements> ReportElements { get; set; }
}
public class ReportElements
{
[Key, Column(Order = 1)]
public int ReportId { get; set; }
[Key, Column(Order = 2)]
public string ElementName { get; set; }
public Boolean Active { get; set; }
}
public class ReportCharts
{
[Key, Column(Order = 1)]
public int ReportId { get; set; }
[Key, Column(Order = 2)]
public string ChartId { get; set; }
public Boolean Active { get; set; }
}
In DbContext:
public DbSet<Report> Reports { get; set; }
// Report entity mapping
protected virtual void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Report>().Property(t => t.ReportId).HasColumnName("ReportId");
modelBuilder.Entity<Report>().Property(t => t.Title).HasColumnName("Title");
modelBuilder.Entity<Report>().Property(t => t.DateRange).HasColumnName("DateRange");
modelBuilder.Entity<Report>().Property(t => t.Layout).HasColumnName("Layout");
modelBuilder.Entity<Report>().Property(t => t.DateFrom).HasColumnName("DateFrom");
modelBuilder.Entity<Report>().Property(t => t.DateTo).HasColumnName("DateTo");
modelBuilder.Entity<Report>().Property(t => t.OwnerId).HasColumnName("OwnerId");
modelBuilder.Entity<Report>().Property(t => t.DateCreated).HasColumnName("DateCreated");
modelBuilder.Entity<Report>().Property(t => t.Active).HasColumnName("Active");
modelBuilder.Entity<Report>().HasMany(t => t.ReportElements).WithRequired().HasForeignKey(c => c.ReportId);
modelBuilder.Entity<Report>().HasMany(t => t.ReportCharts).WithRequired().HasForeignKey(p => p.ReportId);
modelBuilder.Entity<ReportElements>().Property(c => c.ElementName).HasColumnName("ElementName");
modelBuilder.Entity<ReportElements>().HasKey(c => new { c.ReportId, c.ElementName, c.Active });
modelBuilder.Entity<ReportCharts>().Property(p => p.ChartId).HasColumnName("ChartId");
modelBuilder.Entity<ReportCharts>().HasKey(c => new { c.ReportId, c.ChartId, c.Active });
}
In EF repository:
public void RemoveReport(Report rep)
{
context.Reports.Remove(rep);
context.SaveChanges();
}
When I perform delete it deletes only from Report table, and not from all three. When I do save report it saves in all three tables. So don't really understand what is wrong.
Many thanks for your help
You need to look into cascading delete options in Entity Framework an apply them as you need them.
Try this:
modelBuilder.Entity<Report>().HasMany(t => t.ReportElements)
.WithRequired()
.HasForeignKey(c => c.ReportId)
.WillCascadeOnDelete(true);
modelBuilder.Entity<Report>().HasMany(t => t.ReportCharts)
.WithRequired()
.HasForeignKey(p => p.ReportId)
.WillCascadeOnDelete(true);

Fluent NHibernate - Mapping one-to-many using 2 columns

I have a db schema along the lines of:
Product
ID
ProductName
Description
StoreBrand
ProductVariation
VariationID
ProductID
Size
StoreBrand
Price
Classes, predictably, look a bit like this:
public class Product
{
public virtual int ID { get; set; }
public virtual string ProductName { get; set; }
public virtual string Description { get; set; }
public virtual string StoreBrand { get; set; }
public virtual IEnumerable<ProductVariation> Variations { get; set; }
}
public class ProductVariation
{
public virtual int VariationID { get; set; }
public virtual int ProductID { get; set; }
public virtual Product Product {get; set;}
public virtual string Size { get; set; }
public virtual double Price { get; set; }
}
I've got the mapping classes like this:
public class ProductMapper : ClassMap<Product>
{
public ProductMapper()
{
Id(x => x.ID);
Map(x => x.ProductName);
Map(x => x.Description);
Map(x => x.StoreBrand);
HasMany(x => x.Variations)
.KeyColumn("ProductID");
}
}
public class ProductVariationMapper : ClassMap<ProductVariation>
{
public ProductVariation()
{
Id(x => x.ID);
Map(x => x.ProductID);
Map(x => x.Size);
Map(x => x.Price);
References(x => x.Product)
.Column("ProductID");
}
}
This is kind of working...
However, what I need to do is tie the Product.Brands together with the ProductVariation.Brands as well... (and vice versa)
So querying Product, returns a list of it's ProductVariations for that brand...
(Notice, ProductVariation doesn't have a property in the class, but it has the column for mapping)
ProductVariation.ID is non unique.
The key is ProductVariation.ID and ProductVariation.Brand (on the database)
public class Product
{
public virtual int ID { get; set; }
public virtual string StoreBrand { get; set; }
public virtual string ProductName { get; set; }
public virtual string Description { get; set; }
public virtual IEnumerable<ProductVariation> Variations { get; set; }
public override Equals(object obj)
{
return Equals(obj as Product)
}
public override Equals(Product other)
{
return (other != null) && (Id == other.Id) && (StoreBrand == other.StoreBrand);
}
public override GetHashCode()
{
unchecked
{
return Id.GetHashCode() * 397 + StoreBrand.GetHashCode();
}
}
}
public class ProductVariation
{
public virtual int ID { get; set; }
public virtual Product Product {get; set;}
public virtual string Size { get; set; }
public virtual double Price { get; set; }
}
public class ProductMapper : ClassMap<Product>
{
public ProductMapper()
{
// Id alone is not unique, hence compositeId
CompositeId()
.KeyProperty(x => x.ID)
.KeyProperty(x => x.StoreBrand);
Map(x => x.ProductName);
Map(x => x.Description);
HasMany(x => x.Variations)
.KeyColumn("ProductID", "StoreBrand");
}
}
public class ProductVariationMapper : ClassMap<ProductVariation>
{
public ProductVariation()
{
Id(x => x.ID);
Map(x => x.Size);
Map(x => x.Price);
References(x => x.Product)
.Column("ProductID", "StoreBrand");
}
}

Categories

Resources