fluent nhibernate mapping issue - nhibernate

I have two objects Customer_policy and policy_maturity.
public class Customer_policy
{
public virtual String policy_no { get; set; }
public virtual DateTime maturity_date { get; set; }
public virtual Boolean matured_status { get; set; }
}
public class Policy_maturity
{
public virtual string policy_no { get; set; }
public virtual string customer_id { get; set; }
public virtual float maturity_amt { get; set; }
public virtual string policy_type { get; set; }
public virtual DateTime pay_date { get; set; }
}
When a customer creates a policy Customer_policy is getting populated but Policy_maturity should remain empty(which I have already done). When a policy matures I want to insert a row in Policy_maturity and update matured_status field of the corresponding Customer_policy. What type of mapping should I do so that inserting and update gets accomplished by hitting the database only one time ??? Thanx for your suggestions.

a suggestion:
public class CustomerPolicy
{
public virtual String PolicyNumber { get; private set; }
public virtual DateTime MaturityDate { get; set; }
public virtual PolicyMaturity Maturity { get; private set; }
public virtual Boolean HasMatured { get { return Maturity != null; } }
public virtual void DoMature(Customer customer, float maturity_amt, string policyType, DateTime payDate)
{
DoMature(new PolicyMaturity
{
Customer = customer,
MaturityAmt = maturity_amt,
PolicyType = policyType,
PayDate = payDate,
});
}
/*public*/ virtual void DoMature(PolicyMaturity maturity)
{
Maturity = maturity;
MaturityDate = DateTime.Today;
}
}
public class PolicyMaturity
{
public virtual String PolicyNumber { get; private set; }
public virtual CustomerPolicy Policy { get; set; }
public virtual Customer Customer { get; set; }
public virtual float MaturityAmt { get; set; }
public virtual string PolicyType { get; set; }
public virtual DateTime PayDate { get; set; }
}
class CustomerPolicyMap : ClassMap<CustomerPolicy>
{
public CustomerPolicyMap()
{
Id(cp => cp.PolicyNumber).GeneratedBy.Assigned();
Map(cp => cp.MaturityDate);
HasOne(cp => cp.Maturity);
}
}
class PolicyMaturityMap : ClassMap<PolicyMaturity>
{
public PolicyMaturityMap()
{
Id(cp => cp.PolicyNumber).GeneratedBy.Foreign("Policy");
HasOne(cp => cp.Policy);
References(cp => cp.Customer);
Map(cp => cp.MaturityAmt);
Map(cp => cp.PayDate);
Map(cp => cp.PolicyType);
}
}
then if you save the Updated Customerpolicy NHibernate should batch the two updates

You will need to ask NHibernate to batch the two DML queries. Have a look at this blog post for a detailed description of how to use batching in NHibernate.
Wrapping the two operations in a transaction (as the example in the blog post does) is also a good idea.

Related

Missing type map configuration or unsupported mapping.for Collection of DTO

I was making an API for saving a model where it has one to many relationship with another model. When I applying automapping in it. it is giving me following error:
CreateContestDto -> Contest
tritronAPI.DTOs.CreateContestDto -> tritronAPI.Model.Contest
Type Map configuration:
CreateContestDto -> Contest
tritronAPI.DTOs.CreateContestDto -> tritronAPI.Model.Contest
Destination Member:
Problems
---> AutoMapper.AutoMapperMappingException: Missing type map
configuration or unsupported mapping.
Mapping types:
ProblemDto -> Problem
tritronAPI.DTOs.ProblemDto -> tritronAPI.Model.Problem
at lambda_method(Closure , ProblemDto , Problem , ResolutionContext )
My models are: Contest and Problem a contest contain many problems:
public class Contest
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public ICollection<Problem> Problems { get; set; }
public ICollection<ContestProgrammingLanguage>
ContestProgrammingLanguages { get; set; }
}
public class Problem
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[MaxLength(255)]
public string ProblemName { get; set; }
[ForeignKey("User")]
public string ProblemAuthorId { get; set; }
public virtual User ProblemAuthor { get; set; }
public string AuthorName { get; set; }
//public virtual List<Resources> Resourceses { get; set; }
public string ProblemDescription { get; set; }
public bool IsPublished { get; set; }
public virtual ICollection<Submission> Submissions { get; set; }
public string Tags { get; set; }
//public Guid Contest_Id { get; set; }
public virtual Contest Contest { get; set; }
[ForeignKey("Contest")]
public int? Contest_Id { get; set; }
public short Score { get; set; }
//Timelimit in miliseconds
public int TimeLimit { get; set; }
//MemoryLimit in bytes
public int MemoryLimit { get; set; }
//More than source code limit is not allowed
public int? SourceCodeLimit { get; set; }
public virtual ICollection<TestFile> TestFiles { get; set; } = new
List<TestFile>();
}
public class CreateContestDto
{
public CreateContestDto()
{
this.Problems = new HashSet<ProblemDto>();
}
public string Name { get; set; }
public DateTime StartDate { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndDate { get; set; }
public DateTime EndTime { get; set; }
public string BackgroundImage { get; set; }
public string Description { get; set; }
public ICollection<ProblemDto> Problems { get; set; }
}
public class ProblemDto
{
public int Id { get; set; }
public string ProblemName { get; set; }
}
mapping profile:
CreateMap<CreateContestDto, Contest>().ForMember(
dest => dest.Problems , opt => opt.MapFrom(src =>
src.Problems));
controller code:
public async Task<IActionResult> AddContest([FromBody]
CreateContestDto contest)
{
var con = _mapper.Map<Contest>(contest);
this._uow.ContestRepository.Add(con);
return Ok();
}
I have already tried with reversemap selecting new id in mapping profile
You also need to add mappings for ProblemDTO to Problem:
CreateMap<CreateContestDto, Contest>();
CreateMap<ProblemDto, Problem>();

Web API 2 OData v4 Requesting a Derived Entity Collection keep response 404

I m trying this tutorial: Requesting a Derived Entity Collection
When i make this request:
GET : http://tdd.stooges.com.my/api/paymentAbles?$format=application/json
I get this response:
{
"#odata.context":"http://tdd.stooges.com.my/api/$metadata#paymentAbles",
"value":[
{
"#odata.type":"#EFDB.Topup","id":1
},
{
"#odata.type":"#EFDB.Order","id":7
}
]
}
It is OK. But when i try this request:
GET : http://tdd.stooges.com.my/api/paymentAbles/EFDB.Order?$format=application/json
I get the response 404
I found a similar question on stackoverflow:
WCF Data Service gives 404 when making OData requests for derived types,
but the solution make all http request return 500 internal error.
How can I solve the problem? You can use this site: http://tdd.stooges.com.my for testing (for example using firebug to view teh request/response details).
Update :
modelBuilder.Entity<PaymentAble>()
.Map<Topup>(s => s.Requires("type").HasValue("topup"))
.Map<Order>(m => m.Requires("type").HasValue("order"));
[Table("payment_able")]
public abstract class PaymentAble
{
[Key]
public int id { get; set; }
public double amount { get; set; }
public string code { get; set; }
public string statusEnum { get; set; }
[ForeignKey("member")]
public int member_id { get; set; }
public virtual Member member { get; set; }
public virtual Payment payment { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTimeOffset rowCreatedDT { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
[ConcurrencyCheck]
public byte[] rowVersion { get; set; }
[ForeignKey("rowCreator")]
public int rowCreatorLoginPerson_id { get; set; }
[ForeignKey("rowLastModifiedBy")]
public int rowLastModifiedByLoginPerson_id { get; set; }
public virtual LoginPerson rowCreator { get; set; }
public virtual LoginPerson rowLastModifiedBy { get; set; }
}
public class Topup : PaymentAble
{
}
public class Order : PaymentAble
{
[Column("order_GSTPercent")]
public double GSTPercent { get; set; }
[Column("order_clientName")]
public string clientName { get; set; }
[Column("order_clientEmail")]
public string clientEmail { get; set; }
[Column("order_clientHp")]
public string clientHp { get; set; }
public virtual List<OrderItem> items { get; set; }
}
[Table("order_item")]
public class OrderItem : RowInfo
{
[Key]
public int id { get; set; }
public int qty { get; set; }
public double amount { get; set; }
[ForeignKey("order")]
public int order_id { get; set; }
public virtual Order order { get; set; }
public virtual OrderCard card { get; set; }
}
public static IEdmModel GetModel()
{
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<LoginPerson>("loginPersons");
builder.EntitySet<Admin>("admins");
builder.EntitySet<Member>("members");
builder.EntitySet<Card>("cards");
builder.EntitySet<CardPackage>("cardPackages");
builder.EntitySet<Game>("games");
builder.EntitySet<Img>("imgs");
builder.EntitySet<Currency>("currencys");
builder.EntitySet<Topup>("topups");
builder.EntitySet<Order>("orders");
builder.EntitySet<OrderItem>("OrderItems");
builder.EntitySet<Payment>("payments");
builder.EntitySet<PaymentAble>("paymentAbles");
builder.Namespace = "RPC"; //test only
var gettotalFn = builder.EntityType<PaymentAble>().Collection.Function("getTotal");
gettotalFn.Returns<int>();
return builder.GetEdmModel();
}
config.MapODataServiceRoute("odata", "api", GetModel());
[ODataRoutePrefix("paymentAbles")]
public class PaymentAblesController : BaseController
{
[ODataRoute("")]
[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
public IQueryable<PaymentAble> get()
{
return db.paymentAbles;
}
public async Task<IHttpActionResult> getTotal()
{
return Ok(15);
}
}

Fluent NHibernate mapping throws an exception of 'Id is not mapped'

I need help with auto mapping in Fluent Nhibernate. Here's the tables I want to have in my app (they are many of them, but I want to start from mapping only a few of them)
Well, I'd like to use the AutoMapping functionality because I don't want to write the mapping classes for more than 100 tables...
Anyway, here's the error thrown when creating the SessionFactory (the code is at the end of this post)
The entity 'FilterConfig' doesn't have an Id mapped.
Use the Id method to map your identity property. For example: Id(x => x.Id).
Entities (I hope I created them correctly):
public partial class UserLogin
{
public UserLogin()
{
this.UserMessages = new List<UserMessage>();
this.UserMessagesReceivers = new List<UserMessagesReceiver>();
}
public virtual int ID { get; set; }
public virtual int UserTypeID { get; set; }
public virtual int? StudentID { get; set; }
public virtual int? HeadmasterID { get; set; }
public virtual int? ParentID { get; set; }
public virtual string UniqueID { get; set; }
public virtual bool ShowMyPhoneNumber { get; set; }
public virtual bool IsBanned { get; set; }
public virtual string Login { get; set; }
public virtual string Password { get; set; }
public virtual bool WasPasswordSent { get; set; }
public virtual string Email { get; set; }
public virtual string UserPicture { get; set; }
public virtual IList<UserMessage> UserMessages { get; set; }
public virtual IList<UserMessagesReceiver> UserMessagesReceivers { get; set; }
}
public partial class UserMessage
{
public UserMessage()
{
this.UserMessagesReceivers = new List<UserMessagesReceiver>();
this.UserMessagesReplies = new List<UserMessagesReply>();
}
public virtual int ID { get; set; }
public virtual DateTime Date { get; set; }
public virtual DateTime? LastCheckDate { get; set; }
public virtual int UserLoginID { get; set; }
public virtual string Description { get; set; }
public virtual bool HasNonCheckedReplies { get; set; }
public virtual UserLogin UserLogin { get; set; }
public virtual IList<UserMessagesReceiver> UserMessagesReceivers { get; set; }
public virtual IList<UserMessagesReply> UserMessagesReplies { get; set; }
}
public partial class UserMessagesReceiver
{
public UserMessagesReceiver()
{
this.WasMessageChecked = false;
this.UserMessagesReplies = new List<UserMessagesReply>();
}
public virtual int ID { get; set; }
public virtual int UserMessagesID { get; set; }
public virtual int ReceiverLoginID { get; set; }
public virtual bool WasMessageChecked { get; set; }
public virtual DateTime? LastCheckedDate { get; set; }
public virtual UserLogin UserLogin { get; set; }
public virtual UserMessage UserMessage { get; set; }
public virtual IList<UserMessagesReply> UserMessagesReplies { get; set; }
}
public partial class UserMessagesReply
{
public UserMessagesReply()
{
}
public virtual int ID { get; set; }
public virtual DateTime Date { get; set; }
public virtual int UserMessagesID { get; set; }
public virtual int? UserMessagesReceiverID { get; set; }
public virtual string Description { get; set; }
public virtual UserMessage UserMessage { get; set; }
public virtual UserMessagesReceiver UserMessagesReceiver { get; set; }
}
Configuration:
public class AutomappingConfiguration : DefaultAutomappingConfiguration
{
public override bool IsId(Member member)
{
return member.Name == member.DeclaringType.Name + "ID";
}
}
private static AutoPersistenceModel CreateAutomappings()
{
return AutoMap.AssemblyOf<AutomappingConfiguration>(new AutomappingConfiguration());
}
private static ISessionFactory CreateSessionFactory()
{
var cfg = new AutomappingConfiguration();
return Fluently.Configure()
.Database(MySQLConfiguration.Standard
.ConnectionString("..."))
.Mappings(m => m.AutoMappings
.Add(AutoMap.AssemblyOf<UserLogin>(cfg))
.Add(AutoMap.AssemblyOf<UserMessage>(cfg))
.Add(AutoMap.AssemblyOf<UserMessagesReceiver>(cfg))
.Add(AutoMap.AssemblyOf<UserMessagesReply>(cfg)))
.BuildSessionFactory();
}
in the configuration you said that the Ids are named like UserLoginID but in the class they are defined as public virtual int ID { get; set; } so change
return member.Name == member.DeclaringType.Name + "ID";
to
return member.Name == "ID";
Some additional info:
CreateAutomappings() seems to be not used
AutomappingConfiguration should at least override ShouldMap(Member) to filter on the namespace (e.g. member.Namespace.StartsWith(typeof(UserMessage).Namespace)) otherwise sooner or later utility classes and the like will be mapped as well
AutoMap.AssemblyOf<> should be called per assembly containing types not per type

Code first - navigation property with different name than class

I have several cases where my navigation property is repeated in a class, or I don't want it to have the same name as the class it represents. Example:
public class Employee
{
public Guid EmployeeId { get; set; }
public string Name { get; set; }
}
public class Project
{
public Guid ProjectId { get; set; }
public DateTime Start { get; set; }
public Guid ResponsibleId { get; set; }
public virtual Employee Responsible { get; set; }
public Guid OwnerId { get; set; }
public virtual Employee Owner { get; set; }
}
When using EF Code First, it messes up the foreign keys, creates new ones with different names. How do I handle this?
Thanks a lot!
This should help:
public class Employee
{
public Guid EmployeeId { get; set; }
public string Name { get; set; }
public virtual ICollection<Project> ResponsibleProjects { get; set; }
public virtual ICollection<Project> OwnedProjects { get; set; }
}
public class Project
{
public Guid ProjectId { get; set; }
public DateTime Start { get; set; }
public Guid ResponsibleId { get; set; }
public virtual Employee Responsible { get; set; }
public Guid OwnerId { get; set; }
public virtual Employee Owner { get; set; }
}
public YourContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Project>()
.HasRequired(p => p.Owner)
.WithMany(e => e.OwnedProjects )
.HasForeignKey(p => p.OwnerId );
modelBuilder.Entity<Project>()
.HasRequired(p => p.Responsible)
.WithMany(e => e.ResponsibleProjects )
.HasForeignKey(p => p.ResponsibleId );
base.OnModelCreating(modelBuilder);
}
Note how relations are defined for both ends and how I point what exact field is used as a foreign key.
I ended up doing this, which works:
public class Employee
{
public Guid EmployeeId { get; set; }
public string Name { get; set; }
}
public class Project
{
public Guid ProjectId { get; set; }
public DateTime Start { get; set; }
public Guid ResponsibleId { get; set; }
[ForeignKey("ResponsibleId")]
public virtual Employee Responsible { get; set; }
public Guid OwnerId { get; set; }
[ForeignKey("OwnerId")]
public virtual Employee Owner { get; set; }
}
Thanks to Wiktor for the comment that lead to the solution.

Parent Child Relationship in ASP.NET MVC 4

I am trying to do this:
Hibernate: Parent-Child Relationship to Itself
but in ASP.NET MVC 4
here are my 2 models (which i have no clue if this is the correct way to do this):
public class Group
{
public int GroupID { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
public virtual ICollection<GroupRelation> GroupRelations { get; set; }
}
public class GroupRelation
{
public int GroupRelationID { get; set; }
public int? ParentID { get; set; }
public int? ChildID { get; set; }
[ForeignKey("ParentID")]
public virtual Group ParentGroups { get; set; }
[ForeignKey("ChildID")]
public virtual Group ChildGroups { get; set; }
}
Here is my Context(again no clue if this is right):
public class TaskTrackerContext : DbContext
{
public DbSet<Group> Groups { get; set; }
public DbSet<GroupRelation> GroupRelations { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Group>()
.HasMany(g => g.GroupRelations).WithOptional(g => g.ChildGroups).HasForeignKey(g => g.ChildID);
modelBuilder.Entity<Group>()
.HasMany(g => g.GroupRelations).WithOptional(g => g.ParentGroups).HasForeignKey(g => g.ParentID);
}
}
With this setup i get the following in my database:
(i tried to put in a pic or a link to a pic and it wont let me...)
So it makes the 2 relationships i am expecting "PK_GroupID - FK_ParentID" and "PK_GroupID - FK_ChildID", but then it creates an extra column called "Group_GroupID" and makes the following relationship: "PK_GroupID - FK_Group_GroupID".
So what am I doing wrong?