Really stuck with Linq to SQL grouping and summing, have searched everywhere but I don't understand enough to apply other solutions to my own.
I have a view in my database called view_ProjectTimeSummary, this has the following fields:
string_UserDescription
string_ProjectDescription
datetime_Date
double_Hours
I have a method which accepts a to and from date parameter and first creates this List<>:
List<view_UserTimeSummary> view_UserTimeSummaryToReturn =
(from linqtable_UserTimeSummaryView
in datacontext_UserTimeSummary.GetTable<view_UserTimeSummary>()
where linqtable_UserTimeSummaryView.datetime_Week <= datetime_To
&& linqtable_UserTimeSummaryView.datetime_Week >= datetime_From
select linqtable_UserTimeSummaryView).ToList<view_UserTimeSummary>();
Before returning the List (to be used as a datasource for a datagridview) I filter the string_UserDescription field using a parameter of the same name:
if (string_UserDescription != "")
{
view_UserTimeSummaryToReturn =
(from c in view_UserTimeSummaryToReturn
where c.string_UserDescription == string_UserDescription
select c).ToList<view_UserTimeSummary>();
}
return view_UserTimeSummaryToReturn;
How do I manipulate the resulting List<> to show the sum of the field double_Hours for that user and project between the to and from date parameters (and not separate entries for each date)?
e.g. a List<> with the following fields:
string_UserDescription
string_ProjectDescription
double_SumOfHoursBetweenToAndFromDate
Am I right that this would mean I would have to return a different type of List<> (since it has less fields than the view_UserTimeSummary)?
I have read that to get the sum it's something like 'group / by / into b' but don't understand how this syntax works from looking at other solutions... Can someone please help me?
Thanks
Steve
Start out by defining a class to hold the result:
public class GroupedRow
{
public string UserDescription {get;set;}
public string ProjectDescription {get;set;}
public double SumOfHoursBetweenToAndFromDate {get;set;}
}
Since you've already applied filtering, the only thing left to do is group.
List<GroupedRow> result =
(
from row in source
group row by new { row.UserDescription, row.ProjectDescription } into g
select new GroupedRow()
{
UserDescription = g.Key.UserDescription,
ProjectDescription = g.Key.ProjectDescription,
SumOfHoursBetweenToAndFromDate = g.Sum(x => x.Hours)
}
).ToList();
(or the other syntax)
List<GroupedRow> result = source
.GroupBy(row => new {row.UserDescription, row.ProjectDescription })
.Select(g => new GroupedRow()
{
UserDescription = g.Key.UserDescription,
ProjectDescription = g.Key.ProjectDescription,
SumOfHoursBetweenToAndFromDate = g.Sum(x => x.Hours)
})
.ToList();
Related
I'm working with a legacy Oracle database that has a column on a table which stores boolean values as 'Y' or 'N' characters.
I have mapped/converted this column out like so:
MappingSchema.Default.SetConverter<char, bool>(ConvertToBoolean);
MappingSchema.Default.SetConverter<bool, char>(ConvertToChar);
ConvertToBoolean & ConvertToChar are simply functions that map between the types.
Here's the field:
private char hasDog;
[Column("HAS_DOG")]
public bool HasDog
{
get => ConvertToBoolean(hasDog);
set => hasDog = ConvertToChar(value);
}
This has worked well for simply retrieving data, however, it seems the translation of the following:
var humanQuery = (from human in database.Humans
join vetVisit in database.VetVisits on human.Identifier equals vetVisit.Identifier
select new HumanModel(
human.Identifier
human.Name,
human.HasDog,
vetVisit.Date,
vetVisit.Year,
vetVisit.PaymentDue
));
// humanQuery is filtered by year here
var query = from vetVisits in database.VetVisits
select new VetPaymentModel(
(humanQuery).First().Year,
(humanQuery).Where(q => q.HasDog).Sum(q => q.PaymentDue), -- These 2 lines aren't correctly translated to Y/N
(humanQuery).Where(q => !q.HasDog).Sum(q => q.PaymentDue)
);
As pointed out above, the .Where clause here doesn't translate the boolean comparison of HasDog being true/false to the relevant Y/N values, but instead a 0/1 and results in the error
ORA-01722: invalid number
Is there any way to handle this case? I'd like the generated SQL to check that HAS_DOG = 'Y' for instance with the specified Where clause :)
Notes
I'm not using EntityFramework here, the application module that this query exists in doesn't use EF/EFCore
You can define new mapping schema for your particular DataConnection:
var ms = new MappingSchema();
builder = ms.GetFluentMappingBuilder();
builder.Entity<Human>()
.Property(e => e.HasDog)
.HasConversion(v => v ? 'Y' : 'N', p => p == 'Y');
Create this schema ONCE and use when creating DataConnection
How can i dynamically change the selected columns in the generated sql query when using a linq expression?
Its a new session for each time the query is executed.
Even when I set the MapExp as null after first creation an then changing the bool value to false, it still generates the column in the sql query.
The code runs in a wpf application.
System.Linq.Expressions.Expression<Func<Entity, Model>> MapExp = x => new Model
{
Id=xId,
Count= LoadFormulaField ? x.Count: null,
...
};
var result = session.Query<Entity>().Select(MapExp))
Your problem seems to be the ternary-conditional as part of the expression which is causing the "Count" column to always be queried.
One option to avoid this could be:
var query = session.Query<Entity>();
IQueryable<Model> result = null;
if (LoadFormulaField)
{
result = query.Select(x => new Model
{
Id = x.Id,
Count = x.Count,
});
}
else
{
result = query.Select(x => new Model
{
Id = x.Id,
});
}
Which would get a little less ugly if you separate in a couple of methods I think.
I have this view method -
public ActionResult Index()
{
var db = new ApplicationDbContext();
var auctions = db.Auctions.ToArray();
return View(auctions);
}
which correctly returns an array of all auctions in my database. But I want to return just the most popular ones. I want to do something like this:
public ActionResult Index()
{
var db = new ApplicationDbContext();
var auctions = db.Auctions.getMostPopular.ToArray();
return View(auctions);
}
Where getMostPopular() is a method in my model containing all my auctions and looks like so at the moment:
public static List<Auction> getMostPopular()
{
var query = "SELECT* FROM AUCTIONS WHERE EndTime > CONVERT(date, GETDATE()) ORDER BY viewCount DESC;" }
}
So how do I correctly write this getMostPopular() method?
And is this the correct path to go writing it in the model? Or should I write the query in the controller Index action, and if so what would that look like?
Correct is relative. Your proposed SQL statement would seem to do the trick. Ordering the results by the ViewCount desc would appear to be the main part of implementing your method get most popular. If you're already considering a date filter, you might also consider the top clause such as select top 10 * from Table order by ViewCount desc, to only consider a fixed number of most popular items.
I need to filter some Entities by various fields using "normal" WHERE and IN clauses in a query over my database, but I do not know how to do that with EF.
This is the approach:
Database table
Licenses
-------------
license INT
number INT
name VARCHAR
...
desired SQL Query in EF
SELECT * FROM Licenses WHERE license = 1 AND number IN (1,2,3,45,99)
EF Code
using (DatabaseEntities db = new DatabaseEntities ())
{
return db.Licenses.Where(
i => i.license == mylicense
// another filter
).ToList();
}
I have tried with ANY and CONTAINS, but I do not know how to do that with EF.
How to do this query in EF?
int[] ids = new int[]{1,2,3,45,99};
using (DatabaseEntities db = new DatabaseEntities ())
{
return db.Licenses.Where(
i => i.license == mylicense
&& ids.Contains(i.number)
).ToList();
}
should work
My problem is:
I would like to get all advertistments where id of Description column is equals with Advertistment's column.
Let's say that Advertistment column is connected with Description column.
I would like to gain all description's id where one of its column called type_of_house is equals m.
Then show all advertistment where advertistment's id is equals with description's id.
In short way: advertistment shows info about houses, descriptions store houses type D and M and I want show all advertistments with houses type of M.
This is correct sql:
SELECT * FROM advertistment, description WHERE advertistment.id_advertistment = description.id_description AND description.type_of_house = "m"
I have no idea how write it into zend. I tried something like that. This function I wrote in model folder.
public function takeAll() {
$select = $this->_db->select();
$select->from(array('a' => 'advertistment', 'd' => 'description'));
$select->where('a.id_advertistment = d.id_description AND d.type_of_house = m');
return $select->query()->fetchAll();
}
You're actually quite close. This should work:
public function takeAll() {
$select = $this->_db->select();
$select->from(array('a' => 'advertistment'));
$select->join(array('d' => 'description'), 'a.id_advertistment = d.id_description');
$select->where('d.type_of_house = ?', 'm');
return $this->_db->fetchAll($select);
}