MVC3/LINQ/EF4.1 selecting distinct col values from a result set? - asp.net-mvc-3

How can I select a list of column values from a result set (as distinct) and put into a list?
class T {int id; string name;}
-- Controller...
var query = #"exec someStoredProc";
IEnumerable<T> bb =
db2.Database.SqlQuery<T>(query);
// Something like???:
List<string> Names = bb.SelectDistinct("name"); // returns distinct list of names from result set

Since you just need the distinct list of names, you can project to the name property and the just use Distinct() :
List<string> Names = bb.Select( x=> x.name)
.Distinct()
.ToList();
This requires that you make the name property public, also I would rethink your class name T, how about CustomerName (or whatever else is expressive enough so you know what it means) ?
public class CustomerName
{
public int id{get;set;}
public string name {get;set;}
}

Related

Lite DB not finding inner object query

I have two objects.
[DataContract]
public class Record
{
[DataMember]
public string Id { get; set; }
}
And this class:
public class BatteryStatus : Record
{
[DataMember]
public DateTime RetrieveTime { get; set; }
}
I'm using Lite DB as a local NoSQL option to query and save the data. I'm needing to find and delete the values based after some time. Here's my code doing so:
var col = db.GetCollection<BatteryStatus>(CollectionName);
var test = col.FindAll()
.Where(x => x.Id == status.Id).ToList();
var result = col.Find(Query.EQ("Id", status.Id.ToString())).ToList();
Test returns with the with the object, but the result value doesn't. Lite DB only uses the Query or the BSONId as a way to delete an object. I don't have a BSON id attached to it (it's a referenced definition so I can't change it).
How can I use the "Query" function in order to get a nested value so I can delete it?
Classes has properties, BSON documents has fields. By default, LiteDB convert all property names to same name in BSON document except _id field which is document identifier.
If you want query using Linq, you will use properties expressions. If you are using Query object class, you must use field name.
var result = col.FindById(123);
// or
var result = col.FindOne(x => x.Id == 123);
// or
var result = col.FindOne(Query.EQ("_id", 123));
Find using _id always returns 1 (or zero) document.
I figured out the problem with LiteDB, since I was using the property name of "Id", the BSON interpreted that as the "_id" of the JSON object, and merging their two values. I solve the issue by renaming the "Id" property to something else.

what is a projection in LINQ, as in .Select()

I typically do mobile app development, which doesn't always have .Select. However, I've seen this used a bit, but I don't really know what it does or how it's doing whatever it does. It is anything like
from a in list select a // a.Property // new Thing { a.Property}
I'm asking because when I've seen code using .Select(), I was a bit confused by what it was doing.
.Select() is from method syntax for LINQ, select in your code from a in list select a is for query syntax. Both are same, query syntax compiles into method syntax.
You may see: Query Syntax and Method Syntax in LINQ (C#)
Projection:
Projection Operations - MSDN
Projection refers to the operation of transforming an object into a
new form that often consists only of those properties that will be
subsequently used. By using projection, you can construct a new type
that is built from each object. You can project a property and perform
a mathematical function on it. You can also project the original
object without changing it.
You may also see:
LINQ Projection
The process of transforming the results of a query is called
projection. You can project the results of a query after any filters
have been applied to change the type of the collection that is
returned.
Example from MSDN
List<string> words = new List<string>() { "an", "apple", "a", "day" };
var query = from word in words
select word.Substring(0, 1);
In the above example only first character from each string instance is selected / projected.
You can also select some fields from your collection and create an anonymous type or an instance of existing class, that process is called projection.
from a in list select new { ID = a.Id}
In the above code field Id is projected into an anonymous type ignoring other fields. Consider that your list has an object of type MyClass defined like:
class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
Now you can project the Id and Name to an anonymous type like:
Query Syntax:
var result = from a in list
select new
{
ID = a.Id,
Name = a.Name,
};
Method Syntax
var result = list.Select(r => new { ID = r.Id, Name = r.Name });
You can also project result to a new class. Consider you have a class like:
class TemporaryHolderClass
{
public int Id { get; set; }
public string Name { get; set; }
}
Then you can do:
Query Syntax:
var result = from a in list
select new TemporaryHolderClass
{
Id = a.Id,
Name = a.Name,
};
Method Syntax:
var result = list.Select(r => new TemporaryHolderClass
{
Id = r.Id,
Name = r.Name
});
You can also project to the same class, provided you are not trying to project to classes generated/created for LINQ to SQL or Entity Framework.
My summary is it takes results (or a subset of results) and allows you to quickly restructure it for use in the local context.
The select clause produces the results of the query and specifies the
"shape" or type of each returned element. For example, you can specify
whether your results will consist of complete Customer objects, just
one member, a subset of members, or some completely different result
type based on a computation or new object creation.
Source: http://msdn.microsoft.com/en-us/library/bb397927.aspx
There are a lot of possible uses for this but one is taking a complex object which of many other contains a property that is a string -- say Name -- and allows you to return an enumeration with just the entries of Name. I believe you can also do the opposite -- use that property ( for example) and create / return new type of object while passing in a property or properties.
It means "mapping". Map each element of a sequence to a transformed sequence. I hadn't comprehended its meaning before I looked at the image.
Where does the meaning of the word come from?
Simply, math! https://mathworld.wolfram.com/Projection.html

count based on lookup in LINQ

I have a table (or entity) named Cases. There is another table CaseStatus_Lookup and the primary key of this table is a foreign key in the Cases table.
What I want to do is: For every status type I want the number of count of cases. For e.g. if status = in progress , I want to know how many cases are in that status.
one other thing: I also want to filter the Cases based on UserID.
I tried several ways in LINQ but could not get vary far. I was wondering if someone could help.
try Linq .GroupBy
am assuming your entity structure
suppose your Case Entity is like
public class Case
{
public int Id{get;set;}
public int CaseStatusId{get;set;}
public int UserId{get;set;}
//navigational fields
public virtual CaseStatus CaseStatus {get;set;}
}
and suppose your CaseStatus entity is like:
public class CaseStatus
{
public int Id{get;set;}
public string Name{get;set;}
//navigational fields..
public virtual ICollection<Case> Cases{get;set;}
}
then you can do this:
using (myDbContext db = new myDbContext())
{
var query = db.Cases.GroupBy(case => case.CaseStatus.Name)
.Select(group =>
new {
Name = group.Key,
Cases= group.OrderBy(x => x.Id),
Count= group.Count()
}
).ToList();
//query will give you count of cases grouped by CaseStatus.
}
similarly you can further filter your result based on userId.
Start to explore about Linq .GroupBy
You need a function that returns the sum and takes the status as parameter :- something like below.
MyCaseStatusEnum caseStatus; //Pass your required status
int caseCount = myCases
.Where(r => r.Status == caseStatus)
.GroupBy(p => p.Status)
.Select(q => q.Count()).FirstOrDefault<int>();

Distinct by Attribute inside the item on my collection

I have an IEnumerable<MyObject> collection, with N MyObject elements.
MyObject is a class with a Title, a Description and an ID (as string).
I'd like to have my collection with distinct list of MyObject, due to the ID field.
So if 2 MyObject have got the same ID, one should be deleted (don't care which, I need unique ID).
How can I do it with LINQ?
Tried :
myList = myList.GroupBy(o => o.ID);
but seems I need a cast?
You can implement a custom IEqualityComparer<MyObject>. Then you can use Enumerable.Distinct to filter out duplicates.
class DistinctIdComparer : IEqualityComparer<MyObject> {
public bool Equals(MyObject x, MyObject y) {
return x.Id == y.Id;
}
public int GetHashCode(MyObject obj) {
return obj.Id.GetHashCode();
}
}
Now it's simple:
IEnumerable<MyObject> distinct = myObjects.Distinct(new DistinctIdComparer());
Or you can use Enumerable.GroupBy what is even simpler:
distinct = myObjects.GroupBy(o => o.ID)
.Select(g => g.First());
If you wants only unique id then you can try.
var uniqueIds = myObjects.Select(x=>x.ID).Distinct();
Or for Unique ID Objects
List<MyObject> objs = new List<MyObject> ();
myObjects.ForEach(x=>{
if(objs.Find(y=>y.ID == x.ID)== null)
objs.Add(x);
});

LINQ/Projection - How to sort TableA by non FK column id/name field per TableB?

How can I use LINQ/Projection to sort a list of A objects that contain an id field that references table/object B (B contains id and name).
I want to sort list of A objects that contain B by B.name?
Model (pseudo)
public class A
{
public int AId {get; set;}
public Nullable<int> BId {get; set;}
}
public class B
{
public int BId {get;set;}
public string Name {get;set;}
}
Code in some controller passing in a list of A's that contain B's but sort them by B.Name?
var list = db.As.OrderBy(x => x.BId->References.Name); // Way wrong but using something similar
return(list.ToList()
Basically, looking for the equivalent of this (using projection join or OrderBy from above):
var q1 =
from a in db.As
join b in db.Bs on a.BId equals b.BId
orderby b.Name // <- Need this to sort by B's name
select c;
Am I right that you are looking for the equivalent to the LINQ query you have already written above, only that it is based on extension methods instead?
In this case the following should work:
var list = db.As.Where(a => a.BId.HasValue)
.Join(db.Bs, a => a.BId.Value, b => b.BId, (a, b) => new { a, b.Name })
.OrderBy(r => r.Name)
.Select(r => r.a);
I've also added a check to make sure A.BId is not null before getting its value.
Just curious: why can't you use your LINQ query (with the only difference of selecting a instead of c)?

Resources