Add additional data to Linq to SQL result - linq-to-sql

I have Linq to SQL query which return one field with Url and I bind it to asp.net combobox. I need to add new virtual record("All Url") to Linq to SQL result before binding the result. How to do that?
var results =
dataAccess.Statistics.
Where(s => s.DateStamp >= minDate && s.DateStamp <= DateTime.UtcNow && s.UserId == userId).
GroupBy(s => s.Url).
Where(g => g.Count() > 1).
OrderBy(g => g.Count()).
Select(g => new { Url = dataAccess.getDomain(g.Key) });
ddlDomain.DataSource = results;
ddlDomain.DataBind();

Add an item to the combobox, then append the databound items:
ddlDomain.Items.Add(new ListItem() { Text = "All Url" });
ddlDomain.AppendDataBoundItems = true;
ddlDomain.DataSource = results;
ddlDomain.DataBind();

Related

Is there a way to select group by elements that are navigation properties in linq to sql

I've a query, something like this
var ReportData = db.PY_History_TransactionTAB.AsEnumerable()
.Where(x => x.SystemCode == SysCode)
.GroupBy(x => new { x.EmployeeCode, x.EmployeeMaster.Emp_FullName});
For x.EmployeeCode selection of GroupBy member, it is easy to do :
ReportData.Select(x => new PY_History_TransactionTAB
{
EmployeeCode = x.Key.EmployeeCode,
}
But, what if I want to select the next GroupBy member i.e. x.EmployeeMaster.Emp_FullName, How do I do this? so that I get it right at my strongly typed view.
ReportData.Select(x => new
{
EmployeeCode = x.Key.EmployeeCode,
EmployeeName = x.Key.Emp_FullName,
}
I found the solution. So, if you have a navigation property, just place it in select() in this way :
ReportData.Select(x => new PY_History_TransactionTAB
{
EmployeeCode = x.Key.EmployeeCode,
EmployeeMaster = x.First().EmployeeMaster
}
Now you can have all properties of EmployeeMaster class as well.

Telerik Line Graph Categories Null

I have tried everything I know to do but I cannot seem to get this to work...
My goal is to show tickets submitted in the past two weeks. I have already done all the logic on the back side of my MVC project but I cannot seem to display it properly. I just get a blank line graph with the legend to the right. I have provided my Razor code and the JSON return data. Please help. Thanks.
#(Html.Kendo().Chart<NewTicketsTwoWeekGraph>()
.Name("TwoWeekTickets")
.DataSource(dataSource => dataSource
.Read(read => read.Action("NewTicketsData_Read", "Home"))
)
.Series(series =>
{
series.Line(d => d.TicketCount).Name("Ticket Count");
})
.CategoryAxis(axis => axis
.Categories(t => t.TicketDate).Date().BaseUnit(ChartAxisBaseUnit.Days)
.Labels(labels => labels.Rotation(-90))
.Crosshair(c => c.Visible(true))
)
.ValueAxis(axis => axis.Numeric()
.Labels(labels => labels.Format("{0:N0}"))
.MajorUnit(10)
)
)
JSON Return:
{"Data":[{"TicketCount":1,"TicketDate":"\/Date(1426651200000)\/","TicketDateString":"2015-03-18"},
{"TicketCount":2,"TicketDate":"\/Date(1426564800000)\/","TicketDateString":"2015-03-17"}],"Total":2,"AggregateResults":null,"Errors":null}
The problem was with the JSON data being sent back. It doesnt like be wrapped in the "Data" array.
So I changed up my ActionResult to fix this...
public ActionResult _NewTicketCtOverTwoWeeks_Read([DataSourceRequest]DataSourceRequest request, string username)
{
using (var ctx = new GuardianContext())
{
var startDate = DateTime.Now.AddDays(-14);
var graphData = from ticket in ctx.TICKETS
where ticket.CREATED > startDate
group ticket by DbFunctions.TruncateTime(ticket.CREATED)
into a
orderby a.Key
select new TicketCount() { TicketCt = a.Count(), TicketDate = (DateTime)a.Key, TicketDateString = a.Key.ToString().Substring(0, 10) };
return Json(graphData.ToList());
}
}
So now my JSON request returns the following...
[{"TicketCt":2,"TicketDate":"\/Date(1426564800000)\/","TicketDateString":"2015-03-17"},{"TicketCt":11,"TicketDate":"\/Date(1426651200000)\/","TicketDateString":"2015-03-18"},{"TicketCt":20,"TicketDate":"\/Date(1426737600000)\/","TicketDateString":"2015-03-19"}]

Conditional Anonymous type

I am working on Web API and using Anonymous type to make JSON as output. I am stuck in the following scenario:
If there is no record(VALUE) available then i don't want to show that KEY. Meaning, Key should only appear when and only when there is value.
Below is the JSON object i am creating -
"TU": [
{
"BLOCK": [
[
"00:00",
"00:59"
]
]
}
],
"WE": [],// empty
"TH": [],// empty
"FR": [],// empty
"SA": [] // empty
Here for Tuesday we do have records and hence its showing but later for WE,TH,FR,SA there are not records and hence i don't want to show them so my result will be MO/TU only.
I am using below code:
var result = new
{
CustomerID = custId,
DeviceID = dId,
Kind = kind,
WebList = filter.Select(filt => new
{
URL = filt.FilterName,
TimeBlockFlag = new ChicoHelper().GetFlag(browserlimit, filt.ID, filt.FilterOptionID, KindId),
DAILY = browserlimit.Where(xx => xx.FilterID == filt.ID && xx.OptionTypeID == daily).Select(xx => xx.BlockTimeLimit).SingleOrDefault(),
WEEKLY = browserlimit.Where(xx => xx.FilterID == filt.ID && xx.OptionTypeID == weekly).Select(xx => xx.BlockTimeLimit).SingleOrDefault(),
MONTHLY = browserlimit.Where(xx => xx.FilterID == filt.ID && xx.OptionTypeID == monthly).Select(xx => xx.BlockTimeLimit).SingleOrDefault(),
HASVALUES = browserlimit.Where(xx => xx.FilterID == filt.ID).Count() > 0 ? 1 : 0,
BLOCKTYPE = new ChicoHelper().GetBlockType(browserlimit,filt.ID,filt.FilterOptionID,KindId),
SU = blockedlimit.Where(x => x.OptionID == sunday && x.FilterID == filt.ID).GroupBy(x => new { x.BlockDay })
.Select(x => new
{
BLOCK = x.Select(y =>
new[] { y.BlockStartTime.MakeFormatedTime(), y.BlockEndTime.MakeFormatedTime() }
)
}),
MO = blockedlimit.Where(x => x.OptionID == monday && x.FilterID == filt.ID).GroupBy(x => new { x.BlockDay })
.Select(x => new
{
BLOCK = x.Select(y =>
new[] { y.BlockStartTime.MakeFormatedTime(), y.BlockEndTime.MakeFormatedTime() }
)
}),
TU = blockedlimit.Where(x => x.OptionID == tuesday && x.FilterID == filt.ID).GroupBy(x => new { x.BlockDay })
.Select(x => new
{
BLOCK = x.Select(y =>
new[] { y.BlockStartTime.MakeFormatedTime(), y.BlockEndTime.MakeFormatedTime() }
)
}),
// if i can put some condition like if there is not record for WE then don't show it.
WE = blockedlimit.Where(x => x.OptionID == wednesday && x.FilterID == filt.ID).GroupBy(x => new { x.BlockDay })
.Select(x => new
{
BLOCK = x.Select(y =>
new[] { y.BlockStartTime.MakeFormatedTime(), y.BlockEndTime.MakeFormatedTime() }
)
}),
The main reason for doing this is to reduce the JSON size which will be consumed by Mobile Devices.
Please help me with this.
The properties of an anonymous type are fixed at compile-time - you can't make them conditional. However, some other approaches you might want to think about:
You could investigate whether a property is still included in the JSON representation if its value is null. If it's not, you could add an extension method NullIfEmpty() which returns null if its input is empty.
You could try performing the JSON conversion from the anonymous type in code first, then delete any properties with an empty set of results, then just return that JSON object from the API. (I don't know Web API myself, but there must be a way of saying "Here's a JSON object - ask it for its string representation" rather than using an anonymous type.)
You could ditch the anonymous type entirely, and build up the JSON representation programmatically, setting just the properties you want.
In any approach, I would strongly advise you to extract a common method to come up with the property value based on a day of the week, so you can have:
...
SU = blockedLimit.GetDayBlocks(sunday),
MO = blockedLimit.GetDayBlocks(monday),
TU = blockedLimit.GetDayBlocks(tuesday),
...
There's no reason to have all that code repeated 7 times. In fact, I'd probably refactor that part before doing anything else - it'll make it easier to experiment.

string to int inside linq2sql lambda expression

I have a lambda expression that returns the sum of two fields in a table. The problem is that the field (ExpectedQuantity) is a string, while QtyExpected is an int. I thought I would be able to use int.Parse in my lambda expression, but I get an error saying that SQL cannot translate it.
return new QuantitiesDashboardAggregate()
{
QtyExpected = query.Sum(x => int.Parse(x.ExpectedQuantity)),
QtyReceived = query.Sum(x => int.Parse(x.ReceivedQuantity)),
};
Can someone help?
Here is how I defined the query variable:
IQueryable<Data.POProduct> query = this.Database.POProducts;
// Apply date range
DateRange dateRange = new DateRange(args.DateRangeFilter, args.DateRangeCriteria);
switch (dateRange.DateRangeFilter)
{
case DateRangeFilter.Date:
query = query.Where(po => po.PurchaseOrder.FiscalDate.Date == dateRange.Date);
break;
case DateRangeFilter.FiscalWeek:
query = query.Where(po => (po.PurchaseOrder.FiscalDate.Year == dateRange.Year) &&
(po.PurchaseOrder.FiscalDate.WeekYear == dateRange.Number));
break;
case DateRangeFilter.FiscalPeriod:
query = query.Where(po => (po.PurchaseOrder.FiscalDate.Year == dateRange.Year) &&
(po.PurchaseOrder.FiscalDate.Period == dateRange.Number));
break;
case DateRangeFilter.FiscalYear:
query = query.Where(po => po.PurchaseOrder.FiscalDate.Year == dateRange.Year);
break;
default:
break;
}
Basically Linq to SQL cannot translate your expression, so you should call .ToList() (or .AsEnumerable()) on your query, it will fetch data drom db, and than you can use your expression with int.Parse

Linq - pulling a value from a null query result

I have a linq query that needs to pull a date column out of a row. The expression currently looks like this
myObject.OrderByDescending(s=> s.MyDate).Where(s => s.CRAStatus.Description == "CheckedOut").FirstOrDefault().MyDate)
The problem is that if there are no rows that are "CheckedOut", the query will return a null and attempting to get "MyDate" will throw an exception. We have some verbose solutions, like:
.ForMember(dest => dest.CheckOutDate, opt => opt.MapFrom(src => {
var temp = src.CRAStatusChangeEvents.OrderByDescending(s=> s.MyDate).Where(s => s.CRAStatus.Description == "CheckedOut").FirstOrDefault();
return temp == null ? temp.MyDate : null;
}));
But it would be nice to find something a little more concise. Any Ideas?
Why not
myObject.OrderByDescending(s=> s.MyDate)
.Where(s => s.CRAStatus.Description == "CheckedOut")
.Select(s => s.MyDate as DateTime?)
.FirstOrDefault();
or
myObject.Where(s => s.CRAStatus.Description == "CheckedOut")
.Max(s => s.MyDate as DateTime?);
One option is to set the default if empty to an "empty" instance (think of string.Empty--its a known instance that represents an empty result):
var date = (myObject
.OrderByDescending(s=> s.MyDate)
.Where(s => s.CRAStatus.Description == "CheckedOut")
.DefaultIfEmpty(MyObject.Empty)
.FirstOrDefault()).MyDate;
Here's a snippet that shows how it works:
var strings = new string[]{"one", "two"};
var length =
(strings.Where(s=>s.Length > 5)
.DefaultIfEmpty(string.Empty)
.FirstOrDefault()).Length;
run that and length is 0. Remove the DefaultIfEmpty line and you get a NRE.
var checkedOut = myObject.Where(s => s.CRAStatus.Description == "CheckedOut");
if (checkedOut.Count() > 0) {
var result = checkedOut.Max(s=> s.MyDate).MyDate;
}
How about an extension method?
static class MyObjectEnumerableExtensions
{
public static TMember GetMemberOfFirstOrDefault<TMember>(this IEnumerable<MyObject> items, Func<MyObject, TMember> getMember)
{
MyObject first = items.FirstOrDefault();
if (first != null)
{
return getMember(first);
}
else
{
return default(TMember);
}
}
}
Sample usage:
List<MyObject> objects = new List<MyObject>();
objects.Add(new MyObject { MyDate = DateTime.MinValue });
var filteredObjects = from s in objects where s.MyDate > DateTime.MinValue select s;
DateTime date = filteredObjects.GetMemberOfFirstOrDefault(s => s.MyDate);
Console.WriteLine(date);