Asp.net, C#, Linq and Array usage, - asp.net

var result = (from p in productInQuery
join o in orderInfoQuery on p.refNo equals o.refNo
join x in productQuery on p.productNo equals x.no
join t in productOutQuery on p.no equals t.productInNo into productIn
from t in productIn.DefaultIfEmpty()
//let dateOut = (from m in orderInfoQuery where m.refNo == t.refNo select m.delivered).FirstOrDefault()
orderby o.processDate descending
select new
{
modelNo = x.modelNo,
mfgNo = p.mfgNo,
serialNo = p.serialNo,
poNo = p.poNo,
lbs = p.lbs,
width = p.width,
height = p.height,
depth = p.depth,
qty = p.qty,
dateIn = o.processDate,
dateOut = (DateTime?)(from m in orderInfoQuery where m.refNo == t.refNo select m.processDate).FirstOrDefault()
}).ToArray();
I want to add this result into iTextSharp table cell.
but I don't know how to do,
I tried,
int resultSize = result.Length;
/*
for (int j = 0; j < resultSize; j++)
{
table.AddCell(result[j]);
}
*/
foreach (string[] test in result) //Error : Unable to cast object of type
{
int testSize = test.Length;
for (int j = 0; j < testSize; j++)
{
table.AddCell(test[j]);
}
}
but I lost way :(
anybody knows, please advice me~
[EDIT]
int resultSize = result.Length; //192
test does have a fields...
[EDIT 2]
Actually the result be returned from Model.
PJ.WebUI.Models Reports Class
public class Reports
{
public Array GetTransaction(){
OrdersRepository ordersRepository = new OrdersRepository();
var productInQuery = ordersRepository.ProductIn;
var productOutQuery = ordersRepository.ProductOut;
var productQuery = ordersRepository.Product;
var orderInfoQuery = ordersRepository.OrderInfo;
var result = (from p in productInQuery
join o in orderInfoQuery on p.refNo equals o.refNo
join x in productQuery on p.productNo equals x.no
join t in productOutQuery on p.no equals t.productInNo into productIn
from t in productIn.DefaultIfEmpty()
//let dateOut = (from m in orderInfoQuery where m.refNo == t.refNo select m.delivered).FirstOrDefault()
orderby o.processDate descending
select new
{
modelNo = x.modelNo,
mfgNo = p.mfgNo,
serialNo = p.serialNo,
poNo = p.poNo,
lbs = p.lbs,
width = p.width,
height = p.height,
depth = p.depth,
qty = p.qty,
dateIn = o.processDate,
dateOut = (DateTime?)(from m in orderInfoQuery where m.refNo == t.refNo select m.processDate).FirstOrDefault()
}).ToArray();
return result;
}
}
And in controller call the method to get the result.
Reports reposrts = new Reports();
var result = reposrts.GetTransaction();
..
foreach (var test in result)
{
table.AddCell(test.modelNo);
}
Then
Error 1 'object' does not contain a definition for 'modelNo' and no extension method 'modelNo' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
So,
I move the model method into controller method (put all together in same method) and run. then it works!.
but the result be used in the other controller too. so I want to keep the result in Model class to reuse.
I want to know why it does not work if the result query is not in same method.
could you help me a little more please?
Thank you very much!

'result' will be an array of the anonymous type you selected to, not an array of string arrays, which is why you are getting an error in the foreach loop.
Your loop should probably look more like the following:
foreach (var test in result)
{
table.AddCell(test.modelNo);
table.AddCell(test.mfgNo);
table.AddCell(test.serialNo);
// etc
}
#Edit 2:
Because the result of GetTransaction() is 'Array', the calling method has no idea what the type is, it just sees it as an array of objects, and, because it is an anonymous type, you can't (reasonably) cast it back to the expected type.
I think your best bet in this case would be to make a new class which has the properties you want to return, e.g.:
public class Transaction
{
public string ModelNo { get; set; }
public string MfgNo { get; set; }
public string SerialNo { get; set; }
// etc. - but with the correct types for the properties
}
Then change the linq query to select into this type, instead of the anonymous type, e.g.:
...
orderby o.processDate descending
select new Transaction
{
ModelNo = x.modelNo,
MfgNo = p.mfgNo,
SerialNo = p.serialNo,
// etc.
...
And change the return type of GetTransaction() from Array to Transaction[].

It's not clear what you are trying to do but I believe you are casting each element of your result as a string incorrectly.
Try this:
foreach (var test in result)
You will probably need to tweak your inner code since test isn't an array, but that should get you past your current error.

Related

How to return this query values

I implement the join query for join two tables. How to return those values.
public List<cartItem> getcartItem(int userId)
{
var data = (from c in _context.cartItems join p in _context.Products
on c.productId equals p.ProId
where c.userId == userId && c.status==false select new {
proName=p.ProductName,
qty=c.quantity,
proImg=p.ImageUrl,
uPricce=p.price
}).ToList();
return data;
}
Assuming these are the properties of a cartItem obj, you just need to assign the select statement to match the return type and new up a cartItem.
...select new cartItem
{
proName = p.ProductName,
qty = c.quantity,
proImg = p.ImageUrl,
uPricce = p.price
}).ToList();

is there a way to get rid of DTO

I am using Entity Framework. I have the following query in which I get data using two tables Application and Employee connected by a foreign key EmployeeID in Application Table. The tables have 1-1 relationship .
Is there a way to simplify the following code and get rid of the DTO Employee1
which is the same as auto generated Employee class
public List<Employee1> GetApplicant(int ApplicationID)
{
var context = new FPSDB_newEntities();
var data = (from a in context.Applications
join e in context.Employees on a.EmployeeID equals e.EmployeeID
where
(
a.ApplicationID == ApplicationID
)
select new Employee1
{
EmployeeID = e.EmployeeID,
SecondEmail = e.SecondEmail,
EmailID = e.EmailID,
Title = e.Title,
Name = e.Name,
Rank = e.Rank,
POBox = e.POBox,
Phone = e.Phone,
JoinDate = e.JoinDate,
Status = e.Status,
DepartmentID = e.DepartmentID.Value,
NameString = e.NameString,
Department = e.Department,
ParentDept = e.ParentDept,
DepartmentAr = e.DepartmentAr,
NameAr = e.NameAr,
NameStringAr = e.NameStringAr,
TitleAr = e.TitleAr
}).ToList();
return data;
}
If you need to return list of Employees, just select e which refers to Employee and don't use Employee1 as a DTO.
public List<Employee> GetApplicant(int ApplicationID)
{
var context = new FPSDB_newEntities();
var data = (from a in context.Applications
join e in context.Employees on a.EmployeeID equals e.EmployeeID
where
(
a.ApplicationID == ApplicationID
)
select e).ToList();
return data;
}
Another way is this, which I would prefer because of readability:
public List<Employee> GetApplicant(int ApplicationID)
{
var context = new FPSDB_newEntities();
var data = context.Applications.Where(p=>p.ApplicationID == ApplicationID).Select(p=>p.Employee).ToList();
return data;
}

The best overloaded method match for int tryparse Error

I'm simply trying to do this, so later on when I save my values in the database they should be set to null incase the textfield is empty.
int? DeliveryAdrID = null;
int.TryParse(TextBoxDeliveryAdrID.Text, out DeliveryAdrID);
But I'm having an error parsing it along.
The above solution should later on make it possible to save empty textbox values in the database as "NULL" instead of 0.
The whole solution:
int parsedValue;
int? DeliveryAdrID = int.TryParse(TextBoxDeliveryAdrID.Text, out parsedValue) ? parsedValue : (int?)null;
int id = Convert.ToInt32(GridViewData.SelectedValue.ToString());
var data = tf.DBTable.Where(a => a.ID == id).FirstOrDefault();
if (data == null)
{
DBTable mt = new DBTable();
mt.Customer = TextBoxCustomer.Text;
mt.Country = TextBoxCountry.Text;
mt.DeliveryAdrID = parsedValue;
tf.DBTable.AddObject(mt);
tf.SaveChanges();
}
else
{
data.Customer = TextBoxCustomer.Text;
data.Country = TextBoxCountry.Text;
data.DeliveryAdrID = parsedValue;
tf.SaveChanges();
}
}
You cannot give a nullable int to int.TryParse. It must be an int. What you are trying to do can be accomplished like so:
int parsedValue;
int? DeliveryAdrID = int.TryParse(TextBoxDeliveryAdrID.Text, out parsedValue) ? parsedValue : (int?) null;

Linq to Entity, selecting group with or without value

Hi Need some help with LINQ query.
I have entity called Shift. This entity has several value field but the ones I am intressted in are ShiftID (int), ShiftDate (DateTime) and GrossMount (decimal(10,2). And this needs to be grouped by month (binding this to a graph in ASP.NET).
I need data for the last 12 months grouped by month.
I have come a bit on the way with this post: Linq to Entity, selecting group without value but not quite all the way.
This is my code for now:
public IQueryable<Shift> GetPastMonths(int months, string accountNumber)
{
_context = new EtaxiEnteties();
var _date = DateTime.Today;
var _firstOfMonth = new DateTime(_date.Year, _date.Month, 31);
var _twelveMonthAgoFirstOfMonth = _firstOfMonth.AddMonths(-12);
// Generate a collection of the months and years for the last 12 months
var _monthYears = Enumerable.Range(-12, 12).Select(monthOffset => { var monthDate = _firstOfMonth.AddMonths(monthOffset); return new { y = monthDate.Year, m = monthDate.Month }; });
var _data = (from _monthYear in _monthYears
join _i in
(from _i in _context.Shifts.Where(acc => acc.Account.AccountNumber == accountNumber)
where _i.ShiftDate >= _twelveMonthAgoFirstOfMonth && _i.ShiftDate < _firstOfMonth
group _i by new { y = _i.ShiftDate.Year, m = _i.ShiftDate.Month } into g
select new { ShiftID = g.Key, GrossAmount = g.Count() }) on _monthYear equals _i.ShiftID into j
from _k in j.DefaultIfEmpty()
select new Shift() { ShiftDate = new DateTime(_monthYear.y, _monthYear.m, 1), GrossAmount = _k != null ? _k.GrossAmount : 0 });
return _data as IQueryable<Shift>;
}
Now I have in return a collection of Shift objects, grouped by month but still missing the GrossAmount. Althoug i would need this from today date (only getting from 1 of current month).
Believe this is my main problem: GrossAmount = g.Count(), but I am not sure
Any LINQ specialist out there that could give me a push?
Use GrossAmount = g.Sum(x => x.GrossAmount) to calculate total GrossAmount value of grouped Shift entities. I believe you have typo in GrossAmount (GrossMount) property name.

Trying to get Distinct() and/or GroupBy(...) in returned ToList

The code is working and returning a good list with (6) items.
However, we are seeing duplicates productSKU. We want to do a
DISTINCt productSKU.
pM = (from oo in ctx.option1
where mArray.Contains(oo.option1Code)
select oo)
.Select(o => new ProductMatch
{
productSKU = o.option1Code,
productPrice = o.price,
option1Desc = o.option1Desc
}).ToList();
I have tried to add Distinct() after the Lambda but I still get (6) items.
I am also getting error when I add GroupBy(...) "Cannot convert lambda expression to type 'string' because it is not a delegate type"
Try this syntax:
pM = (from o in ctx.option1
where mArray.Contains(o.option1Code)
let t = new
{
productSKU = o.option1Code,
productPrice = o.price,
option1Desc = o.option1Desc
}
group o by t into grp
select new ProductMatch
{
productSKU = grp.Key.option1Code,
productPrice = grp.Key.price,
option1Desc = grp.Key.option1Desc
}).ToList();
When you use a Distinct on a lamba expression, the Distinct only looks at the EntityKey for the distinct comparision. You will need to implement your own IEqualityComparer for your select.
internal class UniqueProductComparer : IEqualityComparer<ProductMatch>
{
public bool Equals(ProductMatch x, ProductMatch y)
{
if(Object.ReferenceEquals(x,y)) return true;
if(Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y,null))
return false;
return x.productSKU == y.ProductSKU && x.productPrice == y.productPrice && x.option1Desc == y.option1Desc;
}
public int GetHashCode(ProductMatch match)
{
if (Object.ReferenceEquals(match,null)) return 0;
return match.productSKU.GetHashChode() + match.productPrice.GetHashCode() + match.option1Desc.GetHashCode();
}
}
Then in your lamba, change it to this:
pM = (from oo in ctx.option1
where mArray.Contains(oo.option1Code)
select oo)
.Select(o => new ProductMatch
{
productSKU = o.option1Code,
productPrice = o.price,
option1Desc = o.option1Desc
}).Distinct(new UniqueProductComparer()).ToList();
A slight variation of IAbstractDownvoteFactor's answer
pM = (from oo in ctx.option1
where mArray.Contains(oo.option1Code)
select oo)
.GroupBy(o => o.option1Code)
.Select(g => g.First())
.Select(o => new ProductMatch
{
productSKU = o.option1Code,
productPrice = o.price,
option1Desc = o.option1Desc
}).ToList();
Alternatively, if you use linq heavily and are open to using libraries, there is morelinq that gives you DistinctBy() extension and several other useful extensions.

Resources