Fetch multiple in NPoco when children has its own mapping to do - petapoco

I have been successful with fetching a parent and its children with NPoco FetchManyToOne with this code:
public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public int ParentId { get; set; }
public string Name { get; set; }
}
db.FetchOneToMany<Parent, Child>(parent => parent.Id, child => child.Id,
#"SELECT
P.Id, P.Name,
C.Id, C.ParentId, C.Name
FROM Parent AS P
LEFT JOIN Child AS C ON P.Id = C.ParentId",
id);
Now there is this scenario when a child can belong to a period. A children does not have to belong to a period as this is optional.
In the database the Period table consists of an id column and two datetime columns, Start and End. The Child table has a new column, PeriodId which can contain a null value if it does not belong to a period.
The class Child now gets a new property of type Period. Which can be null or an instance of class Period.
Look at the changes to the class structures:
public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public int ParentId { get; set; }
public string Name { get; set; }
public Period ChildPeriod { get; set; }
}
public class Period
{
public int Id { get; set; }
public DateTime Start { get; set; }
public DateTime End { get; set; }
}
How can I map this sql to my classes?
#"SELECT
P.Id, P.Name,
C.Id, C.ParentId, C.Name,
PE.Id, PE.Start, PE.End
FROM Parent AS P
LEFT JOIN Child AS C ON P.Id = C.ParentId
LEFT JOIN Period AS PE ON C.PeriodId = PE.Id"
So that when a child is a part of a period that period is the value of property ChildPeriod on class Child.
Is it possible or do I have to write two calls to the database and do some manual mapping myself?

Since that's really an outer join on Period where Period will sometimes be null, do your Child class as:
public class Child
{
public int Id { get; set; }
public int ParentId { get; set; }
public string Name { get; set; }
[ResultColumn] public DateTime? Start { get; set; }
[ResultColumn] public DateTime? End { get; set; }
}

Related

Converting SQL query result to Linq result with an new field that is not in the Model

I have an SQL query,
SELECT
c.AssignedTo ,c.CampaignID, c.Name, c.Venue,c.StartedOn,
c.CompletedOn, c.IsOpen, COUNT(C.Name) AS Leads
FROM
Campaign AS c
RIGHT JOIN
Leads AS l ON l.CampaignID = c.CampaignID
GROUP BY
c.AssignedTo, c.CampaignID, c.Name,c.Venue,c.StartedOn, c.CompletedOn, c.IsOpen
ORDER BY
c.AssignedTo
These are my two tables in that query, CAMPAIGNS:
[Table("Campaigns")]
public class Campaigns
{
[Key]
public int CampaignID { get; set; }
[MaxLength(30)]
public string Name { get; set; }
[MaxLength(200)]
public string Venue { get; set; }
[ForeignKey("UsersReference")]
public int AssignedTo { get; set; }
public DateTime StartedOn { get; set; }
public DateTime? CompletedOn { get; set; }
public bool IsOpen { get; set; }
// To Reference Users table using FK
public Users UsersReference { get; set; }
}
and Leads:
[Table("Leads")]
public class Leads
{
[Key]
public int LeadID { get; set; }
[ForeignKey("CampaignsReference")]
public int CampaignID { get; set; }
[MaxLength(30)]
public string ConsumerName { get; set; }
[MaxLength(30)]
public string EmailAddress { get; set; }
[MaxLength(10)]
public string PhoneNo { get; set; }
public string PreferredMoC { get; set; }
public DateTime DateApproached { get; set; }
[ForeignKey("ProductsReference")]
public int ProductID { get; set; }
public string Status { get; set; }
// To access Campaign and Product table through FK
public Campaigns CampaignsReference { get; set; }
public Products ProductsReference { get; set; }
}
My query returns a result likes this in SQL:
The Leads column is just the COUNT() of the columns matching with my CampaignID. I've used context.Campaigns.FromSqlRaw() but since my Campaigns doesn't have another column specifically for the count.
Is there a way to display my new field Count() using EF Core and Linq?
Use LINQ Query for such task.
var query =
from l in ctx.Leads
let c = l.CampaignsReference
group c by new { c.AssignedTo, c.CampaignID, c.Name, c.Venue, c.StartedOn, c.CompletedOn, c.IsOpen } into g
select new
{
g.Key.AssignedTo,
g.Key.CampaignID,
g.Key.Name,
g.Key.Venue,
g.Key.StartedOn,
g.Key.CompletedOn,
g.Key.IsOpen,
Leads = g.Sum(x => x.Name != null ? 1 : 0)
};
var query = query.OrderBy(x => x.AssignedTo);

How to model this correctly in Entity Framework?

I have a requirement that I am not sure how to accomplish, in my existing data I have a list of customers, each customer should be assigned a staffMember to work with them, so would this be a 1 to 1 relationship or a 1 to many relationship, having trouble wrapping my head around how to model the data, as I want to figure out how to model this correctly. Since a staff member can be assigned to many different customers How should I model this? Does this look correct?
What I would like is to have the form pull the list of staff members available from the staff table, when inputting a new customer, ideally by the name
which I figure I could probably do using linq..
public class Customer
{
public int CustomerId { get; set; }
public string Name { get; set; }
public string BusinessName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public DateTime RequestDate { get; set; }
public Staff Staff { get; set; }
public List<CustomerJob> CustomerJobs { get; set; }
}
public class Staff
{
public int ID { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
public string EMail { get; set; }
public int CustomerId { get; set; }
}
Customer have exactly 1 Staff while a single Staff maybe assigned to more than 1 Customer. So this is a one-to-many relation.
It is better that Customer be aware of its Staff. It could be called AssignedStaff. Staff itslef does not need to have a property to show all its Csutomers. Tough you can extract Customer list of a Staff using a simple query.
My recommended class structure is as follow:
public class Customer
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string BusinessName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public DateTime RequestDate { get; set; }
public Staff AssignedStaff { get; set; }
public List<CustomerJob> CustomerJobs { get; set; }
}
public class Staff
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
public string EMail { get; set; }
}
A query for extracting Customer list of a Staff:
var customers = _dbContext.Customers.Where(x => x.AssignedStaff.Id == staffId);

saving reference using ServiceStack ORMLite

I am using ORMLite as my ORM and I am using it with following structure which contains the foreign key relation ship:
public class Order
{
[AutoIncrement]
public int Id { get; set; }
[Reference]
public Item Item { get; set; }
public string ProUserId { get; set; }
public string Details { get; set; }
}
public class Item
{
[AutoIncrement]
public int Id { get; set; }
public string Description { get; set; }
}
As we can see that Order contains the reference to the Item. In DB Order table has a foreign key called ItemId in the table and I have annotated that key in the design view with [Reference] attribute.
I am trying to save the Order with following code:
var order = new Order
{
Item = new Item
{
Id = 3,
Description = "Something"
},
ProUserId = "kunal#kunal.com",
Details = "fdfsdfsd"
};
Db.Save(order,references:true);
I was hoping that ORMLite would pick up the relationship and with ItemID in the Order table but it did not and it did throw following error instead:
Cannot insert the value NULL into column 'ItemId', table 'WebApp.dbo.Order'; column does not allow nulls. INSERT fails.
I tried changing my schema and addred OrderId column in my Item table with reference there and that works fine. But that is not the correct design. Should I make any changes in my code/schema to support this feature?
You still need to provide the foreign key that OrmLite can use to store the relationship, e.g. either on the Child/ForeignKey table:
public class Order
{
[AutoIncrement]
public int Id { get; set; }
[Reference]
public Item Item { get; set; }
public string ProUserId { get; set; }
public string Details { get; set; }
}
public class Item
{
[AutoIncrement]
public int Id { get; set; }
public int OrderId { get; set; } //Parent Table PK
public string Description { get; set; }
}
Or for 1:1 relationships, can be on the Parent table, e.g:
public class Order
{
[AutoIncrement]
public int Id { get; set; }
[Reference]
public Item Item { get; set; }
public int ItemId { get; set; } //Child Table PK
public string ProUserId { get; set; }
public string Details { get; set; }
}
public class Item
{
[AutoIncrement]
public int Id { get; set; }
public string Description { get; set; }
}

not able to get subcategory of particular category in mvc 4 and designing issue of category and subcategory model class

i am working on help desk system in mvc.
i have only one master table for user and technicians.
this is my category class:
public class Category
{
[Key]
public int CategoryId { get; set; }
public string Name { get; set; }
public virtual ICollection<SubCategory> subCategory { get; set; }//category can have more than 1 category
}
This is my Subcategory:
public class SubCategory
{
[Key]
public int SubcategoryId { get; set; }
public string Name { get; set; }
public int CategoryId { get; set; }
public virtual ICollection<TicketInfo> ticketsInfo { get; set; }/to keep track of all tickets under this particular subcategory.
public virtual ICollection<UserDetails> technicianInfo { get; set; }//to keep track of technician and user under this subcategory.
public virtual Category category { get; set; }
}
This is my usermaster(it defines both user and technician)
public class UserDetails
{
public string UserName { get; set; }
[Key]
public int UserId { get; set; }
public string FName { get; set; }
public string LName { get; set; }
public string PhoneNo { get; set; }
public string EmailId { get; set; }
[DataType(DataType.Password)]
public string Password { get; set; }
public int SubcategoryId { get; set; }
public int AddressId { get; set; }
public Boolean IsActive { get; set; }
public DateTime CreatedDate { get; set; }
public virtual ICollection<Role> Roles { get; set; }
public virtual SubCategory subCategory { get; set; }
}
now when i am firing dis query::
public list<Category> FetchTicketDetailsforSubcategory(int categoryId)
{
using (HelpDeskdbContext context = new HelpDeskdbContext())
{
var category = from temp in context.Category where temp.CategoryId == categoryId select temp;
return category;
}
}
it just show me the category but not subcategory under that category.
it show me this on subcategory:The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
can any one figure out what is wrong with my class design??
try this
context.Category.Where(x=>x.CategoryId == categoryId).SelectMany(x=>x.subCategory).ToList()

Polymorphic nhibernate query with projection

Using a single table for a class hierarchy I would like to use a projection to flatten the hierarchy to present a list of results to the user.
Is there a way to do this using HQL or Criteria API without having to issue multiple separate queries or unions?
Classes
public class A {
public virtual long Id { get; set; }
}
public class B : A {
public virtual DateTime SomeDate { get; set; }
public virtual OtherEntity Other { get; set; }
}
public class C : A {
public virtual DateTime? SomeDate { get; set; }
public virtual string Description { get; set; }
}
public class D : A {
public virtual string Description { get; set; }
}
public class OtherEntity {
public virtual string Name { get; set; }
}
SQL Tables:
CREATE TABLE Items (
Id bigint NOT NULL PRIMARY KEY,
Kind char(1) NOT NULL,
SomeDate datetime NULL,
Description NULL
)
CREATE TABLE OtherEntity (
Id bigint NOT NULL PRIMARY KEY,
Name nvarchar(255) NOT NULL
)
Output projection:
public class ItemReport {
// From A.Id
public virtual long Id { get; set; }
// From B.SomeDate or C.SomeDate
public virtual DateTime? SomeDate { get; set; }
// From C.Description or D.Description
public virtual string Description { get; set; }
// From B.OtherEntity.Name
public virtual string OtherName { get; set; }
}