Domanda

I'm new to C#, ASP.NET MVC and SQL Server, but I have got this code working

DateTime startDate = DateTime.Parse(start);
DateTime endDate = DateTime.Parse(end);

ViewData["TotalDuringPeriod"] = db.AlcoholForms.Count(x => x.CreatedDate >= startDate && x.CreatedDate <= endDate);
ViewData["TotalUniqueClientsDuringPeriod"] = db.AlcoholForms.Where(x => x.CreatedDate >= startDate && x.CreatedDate <= endDate).Select(x => x.ClientId).Distinct().Count();
ViewData["TotalGateNew"] = db.AlcoholForms.Count(x => x.ReferredTo == "Gate" && x.Reengagement == false && (x.CreatedDate >= startDate && x.CreatedDate <= endDate));
ViewData["TotalGateReengagment"] = db.AlcoholForms.Count(x => x.ReferredTo == "Gate" && x.Reengagement && (x.CreatedDate >= startDate && x.CreatedDate <= endDate));
ViewData["TotalSwitchNew"] = db.AlcoholForms.Count(x => x.ReferredTo == "Switch" && x.Reengagement == false && (x.CreatedDate >= startDate && x.CreatedDate <= endDate));
ViewData["TotalSwitchReengagement"] = db.AlcoholForms.Count(x => x.ReferredTo == "Switch" && x.Reengagement && (x.CreatedDate >= startDate && x.CreatedDate <= endDate));

List<ReportAlcoholReferals> reportData = db.AlcoholForms.Where(x => x.Referral && (x.CreatedDate >= startDate && x.CreatedDate <= endDate)).Select(x => new ReportAlcoholReferals()
            {
                FirstName = x.Client.FirstName,
                LastName = x.Client.LastName,
                Date = x.CreatedDate,                 
                ClientId = x.ClientId,
                AlcoholForm = x
            }).OrderBy(x => x.AlcoholForm.ReferredTo).ToList();
            return View(reportData);

Now it works but I am hitting the database 7 times? Is there a better way of doing this? How much of a performance issue is it

È stato utile?

Soluzione

Here is how I would handle this, simply in the context of hitting the database less often. There are probably other improvements you could make as well, but that's not what you're asking for.

DateTime startDate = DateTime.Parse(start);
DateTime endDate = DateTime.Parse(end);
List<AlcoholForms> formsList = db.AlcoholForms.Where(x => x.CreatedDate >= startDate && x.CreatedDate <= endDate).ToList();

ViewData["TotalDuringPeriod"] = formsList.Count();
ViewData["TotalUniqueClientsDuringPeriod"] = formsList.Select(x => x.ClientId).Distinct().Count();
ViewData["TotalGateNew"] = formsList.Count(x => x.ReferredTo == "Gate" && x.Reengagement == false);
ViewData["TotalGateReengagment"] = formsList.Count(x => x.ReferredTo == "Gate" && x.Reengagement);
ViewData["TotalSwitchNew"] = formsList.Count(x => x.ReferredTo == "Switch" && x.Reengagement == false);
ViewData["TotalSwitchReengagement"] = formsList.Count(x => x.ReferredTo == "Switch" && x.Reengagement);
List<ReportAlcoholReferals> reportData = formsList.Where(x => x.Referral).Select(x => new ReportAlcoholReferals()
{
    FirstName = x.Client.FirstName,
    LastName = x.Client.LastName,
    Date = x.CreatedDate,                 
    ClientId = x.ClientId,
    AlcoholForm = x
}).OrderBy(x => x.AlcoholForm.ReferredTo).ToList();

return View(reportData);

The list declaration for formsList means that the database will be queried once and store the results in the List object. From there, you can continue to use LINQ to break out your data.

Altri suggerimenti

Your third through sixth queries can be turned from four different counts into one grouping that captures the count of each group:

var lookup = db.AlcoholForms.Where(x => x.CreatedDate >= startDate && 
        x.CreatedDate <= endDate)
    .GroupBy(x => new { x.ReferredTo, x.Reengagement },
        (key, items) => new{key, count = items.Count()})
    .ToDictionary(group => group.key, group => group.count);

ViewData["TotalGateNew"] = lookup[
    new { ReferredTo = "Gate", Reengagement = false }];
ViewData["TotalGateReengagment"] = lookup[
    new { ReferredTo = "Gate", Reengagement = true }];
ViewData["TotalSwitchNew"] = lookup[
    new { ReferredTo = "Switch", Reengagement = false }];
ViewData["TotalSwitchReengagement"] = lookup[
    new { ReferredTo = "Switch", Reengagement = true }];

The number of roundtrips is not necessarily a bad thing. Have you profiled the seven hits to see if they are really taking any time? My guess would be that they aren't, which means you're okay (unless this will be running on a very high volume site).

One alternative would be to write a T-SQL stored procedure that returns the all the values you need in one shot. You could then capture the result as an object, or just a list of ints, or whatever.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top