Linq - Add Row to results for display only - linq-to-sql

I have a linq query that returns a brief order summary - product description and product price that gets bound to a data control. I want to add a row to be bound in this same control that displays tax information. The product description column would simply say "Tax" and the product price column would give a tax amount.
I used to retrieve a DataTable of these results and simply do a NewRow() and then set the datasource of my control as the DataTable. I'm looking for the equivalent technique when using LINQ to SQL. Thanks.

orderSummary.Union(taxRow)

In order to make it easy to add another "row" to the results of the LINQ query, you might want to consider creating a class to hold the results of the query. Then you could convert the results to a List, calculate the tax, and append the tax as an object of the class.
public class OrderSummary
{
public string Description { get; set; }
public decimal Amount { get; set; }
}
var taxRate = ...
var orderSummary = db.Orders.Where( o => o.ID == id )
.Select( o => new OrderSummary
{
Description = o.Product
.Details
.Description,
Amount = o.Qty * o.Product.Price
})
.ToList();
var tax = new OrderSummary
{
Description = "Tax",
Amount = orderSummary.Sum( o => o.Amount * taxRate );
};
orderSummary.Add( tax );
Then you can bind the list to your control using Description as the key and Amount as the value.

Related

Join 3 tables based on column values - Laravel

LEADS TABLE
id
title
owner_id
from_table
EMPLOYEE TABLE
id
first_name
last_name
role
ADMIN TABLE
id
first_name
last_name
role
$users = Leads::query();
return Datatables::make($users)
->editColumn('owner_id', function ($user) {
if($user->from_table == 'employee'){
$emp = Employee::where('id',$user->owner_id)->first();
return $emp->first_name.' '.$emp->last_name.' ('.$emp->role.')';
}
if($user->from_table == 'admin'){
$admin = Admin::where('id',$user->owner_id)->first();
return $admin->first_name.' '.$admin->last_name.' ('.$admin->role.')';
}
})
the above solutions is working fine but we are unable to search column wise induvidual searching in datatables.
what i want is join query something like:
if(leads.from_table == employee)
// fetch data from EMPLOYEE TABLE i.e. LEADS TABLE + EMPLOYEE TABLE
id
title
owner_id
from_table
first_name
last_name
role
if(leads.from_table == admin)
// fetch data from ADMIN TABLE i.e. LEADS TABLE + ADMIN TABLE
id
title
owner_id
from_table
first_name
last_name
role
I think you should change your database structure to use polymorphic relations, they fully comply with your needs - https://laravel.com/docs/5.8/eloquent-relationships#polymorphic-relationships
from_table column should contain the class name of the parent model.
Add in Leads model
public function fetchOwner()
{
return $this->morphTo();
}
Add In Employee Model
public function employee()
{
return $this->morphOne('App\Employee', 'fetchOwner');
}
Add In Admin Model
public function employee()
{
return $this->morphOne('App\Admin', 'fetchOwner');
}
$users = Leads::with('fetchOwner');
return Datatables::make($users)
->editColumn('owner_id', function ($user) {
return $user->fetchOwner->name;
})
thanks to all who tried to help..
I'm answering my own question as i found the answer after 9 days digging everywhere..
so here is the answer:
you may want to replace owner_code by owner_id in your business table.
so i changed the from_table to owner_type & owner_type now should contain the class name as value ex: changed admin to App\Admin & employee to App\Employee in Database
App\Admin.php
public function employee()
{
return $this->morphOne('App\Leads', 'owner');
}
App\Employee.php
public function employee()
{
return $this->morphOne('App\Leads', 'owner');
}
App\Leads.php
public function owner()
{
return $this->morphTo();
}
Thanks to: laravel morphTo how to use custom columns? (EddyTheDove) for pointing out the exact problem..

Spring data JPA , result object has numbers instead of column names

i would like some help trying to do the following.I want to get the number of purchases of each user in the database grouped by his name and id.But it's very hard to do compared to simple sql.
I have the following code in my PurchaseRepository that extends CrudRepository
#Query("SELECT p.user.name as Name,p.user.id as Id,Count(p) as Purchases from Transaction p GROUP BY p.user.id")
List<Object> purchaseNumOfEachUser();
First of all im not sure if this is the right query because i wanted to do Count(*) but says its not valid.
Secondly , the object i get returned when converted to Json via a controller is like
0:{
0:"John",
1:2, //id
2:5 //purchases
}
What i would like to get is
0:{
"Name" : "John",
"Id" : 1 ,
"Purchases" : 2
},
1:{
....
}
Any ideas?
1) The query:
SELECT p.user.name as Name, p.user.id as Id, Count(p) as Purchases
from Transaction p GROUP BY p.user.id
should be
SELECT p.user.name as Name, p.user.id as Id, Count(p) as Purchases
from Transaction p GROUP BY p.user.name, p.user.id
You must group by all rows you are selecting.
2) the result
The result of the query is List if you want to have something meaningful you should consider the constructor expression that let's you create your own objects.
For example
package mypackage;
public class PurchaseInfo {
private final String name;
private final Integer id;
private final Long count;
public PurchaseInfo(String name, Integer id, Long count) {
this.name = name;
this.id = id;
this.cound = count;
}
// getters
}
This class can then be use in the query (please notice the fully qualified class name after NEW):
SELECT NEW mypackage.PurchaseInfo(p.user.name, p.user.id, Count(p))
from Transaction p GROUP BY p.user.name, p.user.id
The result will then be List and you will get it nicely serialized to JSON.
Read more about the Constructor Expression here:
https://vladmihalcea.com/the-best-way-to-map-a-projection-query-to-a-dto-with-jpa-and-hibernate/

PetaPoco is mapping 0 for every Id in my object?

I have the following object:
public class VehicleMake
{
[Column(Name = "MakeID")]
public int Id { get; set; }
public string Name { get; set; }
}
To get a list of vehicle makes, I am doing the following:
var vehicleMakes = _db.Fetch<VehicleMake>(#"SELECT DISTINCT(m.MakeID) AS Id, m.Name
FROM vehicles v
INNER JOIN makes m on m.MakeID = v.Make
WHERE [Year] = #year
ORDER BY m.Name", new { year });
When I run the SQL in SSMS, it returns the correct data, but in VS, it is mapping 0 for every Id property.
Ah, I got it, in case anyone else runs into the problem. Since I am doing:
SELECT DISTINCT(m.MakeID) as Id..., there is no reason to have:
[Column(Name = "MakeID")] since I am aliasing the column as Id already.

LINQ to SQL - Searching column of joined table

I am trying to return a result set that includes rows where any of three strings has a string match. My domain models look like this:
public class Customers
{
public int CustomerID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class BidNames
{
public int BidNameID { get; set; }
public int CustomerID { get; set; }
public string BidName { get; set; }
}
There is a FK between BidName.CustomerID and Customers.CustomerID and it is a one-to-many relationship where there can be multiple BidNames for a single Customer. When searching my customer table I want to bring back all records where there is a string match in FirstName, LastName or any of the associated BidNames. For this example I'll use a BidName search string of "ba".
from c in Customers
where c.FirstName.Contains("ba") || c.LastName.Contains("ba") || c.BidNames.Any(b=>BidNames.BidName.Contains("ba"))
orderby c.LastName, c.FirstName
select new { CustomerID = c.CustomerID, FirstName = c.FirstName, LastName = c.LastName }
It all works until I add the final criteria in the Where clause. I understand that c.BidNames is a collection and I'm looking to see if Any of them have a BidName that contains "ba". Where I'm running into trouble is trying to specify the BidNames.BidName column to search for the string. The code I've written above fails with "BidNames does not contain a definition for 'BidName'"
How do I write the last part of the Where clause so I can search all the BidNames.BidName fields associated with the Customer record? I hope and assume I can use the same syntax to specify the BidName field in the orderby and select clauses as well.
Many thanks,
BK
FINAL ANSWER:
from c in Customers
where
c.FirstName.Contains("ba") ||
c.LastName.Contains("ba") ||
c.BidNames.Any(b=>b.BidName.Contains("ba"))
orderby
c.LastName,
c.FirstName
select new {
CustomerID = c.CustomerID,
FirstName = c.FirstName,
LastName = c.LastName,
BidNames = c.BidNames.OrderBy(b=>b.BidName)
}
Try changing your where clause to
Where c.FirstName.Contains("ba") ||
c.LastName.Contains("ba") ||
c.BidNames.Any(b=>b.BidName.Contains("ba"))
In your Any clause, b is an instance of the BidNames class, so you want to access properties of that rather than the BidNames property of the Customer.

LINQ To SQL SubSelect Like Query

imagine there are two tables.
Order
+----------------+
| ID |
| Name |
+----------------+
OrderStatus
+----------------+
| ID |
| OrderId |
| StatusId |
+----------------+
A Order can have more than one OrderStatus, which could be called OrderStatusHistory.
I'll have an StronglyTypeObject Order, which is descripted as follows
namespace my.project
{
public class Order
{
Int64 OrderId { get; set; }
String Name { get; set; }
Int64 StatusId { get; set; }
}
}
This StatusId in the Order Object is meant to be the current (last) StatusId from the OrderStatus Table.
I have tried to build a IQueryable List of Objects with LINQ. Here is my, not working ;), Linq Code
var result = from r in dbContext.ORDER
select new Order
{
OrderId = r.ID,
Name = r.Name,
StatusId = dbContext.OrderStatus
.Where(p => p.OrderId == r.ID).Last().StatusId
}
I have also tried working with Max(p=>p.XXX) but it hasn't worked out.
Does anyone has a hint on this problem?
Any Help would be much appreciated...
Gordon
Based on your comment, I've updated the below to use First and, in that case, you will need to do an OrderByDescending on the key to get it in the right order.
var result = from r in dbContext.ORDER
select new Order
{
OrderId = r.ID,
Name = r.Name,
StatusId = dbContext.OrderStatus
.Where(p => p.OrderId == r.ID)
.OrderByDescending( p => p.ID )
.First()
.StatusId
}
Also, if you have a FK relationship defined, it should be much easier to get the last StatusId without creating an intermediate object. In this case, I think you can use Last (if the objects are preloaded) since you'll be doing LINQtoObjects, not LINQToSQL. YMMV.
var currentStatus = order.OrderStatuses.Last().StatusId;
The latter could be added as a method on a partial class for ORDER so that you can refer to it as.
var currentStatus = order.CurrentStatus;
public partial class ORDER
{
public int64 CurrentStatus
{
get
{
return this.OrderStatuses.Last().StatusId;
}
}
}
alright, how about this: (take two, order descending and take first .. top 1 )
var result = from r in dbContext.ORDER
select new Order
{
OrderId = r.ID,
Name = r.Name,
StatusId = dbContext.OrderStatus
.Where(p => p.OrderId == r.ID)
.OrderByDescending(p => p.OrderID)
.Select(p => p.StatusId)
.FirstOrDefault()
}