I'm having some trouble with finding the right syntax to accomplish the following:
Is it possible with LINQ (Lambda Expression) to .GroupBy data and instead of using the usual .Sum() or .Count() I want the resulting data to be a List of Int.
I defined my own class named: Filter_IDs. Its constructor needs two parameters:
public int? type; // Represents the object_type column from my database
public List<int?> objects; // Represents the object_id column from my database
I want to load data from my database into this object. The following LINQ query should result in a List of Filter_IDs:
The following LINQ query should result in a List of Filter_IDs:
List<Filter_IDs> filterids = ef.filterLine
.GroupBy(fl => fl.objectType)
.Select(fl => new Filter_IDs { type = fl.Key, objects = fl.Select(x => x.object_id).ToList() })
.ToList();
Using this query gives no building error but gives an 'NotSupportedException' on RunTime.
The database looks like this to give you a better understanding of the data:
http://d.pr/i/mnhq+ (droplr image)
Thanks in advance,
Gerben
I think the problem is the DB is not able to call ToList in the select, nor to create a new Filter_ID.
Try something like this :
List<Filter_IDs> filterids = ef.filterLine.Select(o => new { objectType = o.objectType, object_id=o.object_id})
.GroupBy(fl => fl.objectType).ToList()
.Select(fl => new Filter_IDs { type = fl.Key, objects = fl.Select(x => x.object_id).ToList() })
.ToList();
Maybe you want
IList<Filter_IDs> filterIds = ef.filterline
.Select(fl => fl.objectType).Distinct()
.Select(ot => new Filter_IDs
{
type = ot,
objects = ef.filterline
.Where(fl => fl.objectType == ot)
.Select(fl =>objectType)
.ToList()
}).ToList();
Get the distinct list objectType and use that to subquery for each list of object_id.
However, it seems more efficient to me to just enumerate the values in order,
var results = new List<Filter_IDs>();
var ids = new List<int>();
var first = true;
int thisType;
foreach (var fl in ef.filterLines
.OrderBy(fl => fl.objectType)
.ThenBy(fl => fl.object_Id))
{
if (first)
{
thisType = fl.objectType;
first = false;
}
else
{
if (fl.objectType == thisType)
{
ids.Add(fl.object_Id);
}
else
{
results.Add(new Filter_IDs
{
Type = thisType,
objects = ids
});
thisType = fl.objectType;
ids = new List<int>();
}
}
}
You can use GroupBy on client side:
List<Filter_IDs> filterids = ef.filterLine
.Select(fl=>new {fl.ObjectType, fl.object_id})
.AsEnumerable()
.GroupBy(fl => fl.objectType)
.Select(fl => new Filter_IDs { type = fl.Key, objects = fl.Select(x => x.object_id).ToList() })
.ToList();
Related
Additional information: LINQ to Entities does not recognize the method 'System.String ToString(System.Object)' method, and this method cannot be translated into a store expression.
Ok, "ToString()" cannot be translated into a store expression, and error is clear.
This is my code:
var narudzbe = db.Narudzbe
.Where(x => x.KupacID == id && x.Status == true)
.Select(x => new NarudzbeVM()
{
BrojNarudzbe = x.BrojNarudzbe,
Datum = x.Datum,
KupacID = x.KupacID,
NarudzbaID = x.NarudzbaID,
Otkazano = x.Otkazano,
Status = x.Status,
StavkeNarudzbe = db.NarudzbaStavke
.Where(y => y.NarudzbaID == x.NarudzbaID)
.Select(z => new NarudzbaStavkeVM()
{
Kolicina = z.Kolicina,
NarudzbaID = z.NarudzbaID,
NarudzbaStavkaID = z.NarudzbaStavkaID,
Proizvod = db.Proizvodi
.Select(t => new ProizvodTest()
{
Cijena = t.Cijena,
ProizvodID = t.ProizvodID,
JedinicaMjere = t.JediniceMjere.Naziv,
Naziv = t.Naziv,
Sifra = t.Sifra,
SlikaThumb = Convert.ToString(t.SlikaThumb)
})
.Where(k => k.ProizvodID == z.ProizvodID)
.FirstOrDefault()
}).ToList()
}).ToList();
I want to convert byte[] to string, since my class accept string for attribut "SlikaThumb". So,
SlikaThumb = Convert.ToString(t.SlikaThumb)
t.SlikaThumb is type of byte[]. Is there way to do it in lambda ?
As you've said, Linq to Entities doesn't recognize .ToString() calls; it doesn't know how to convert these into SQL. However, you can run that in memory; simply resolve the objects (call .ToList() or something) and then perform the select statement on the in-memory objects. It'll be Linq to Objects and that'll be permitted.
Whether that will work for the purpose you intend is a different question but you definitely will be able to call .ToString() on any object in this way.
I guess the best thing you could do is retrieve the object from database as they are, by using ToList() or an equivalent method to actually do the query, then after that, you work on the retrieved list to convert to the objects you want to send to Android. As far as I know, there is no translated method to T-SQL from LinqToEntities to convert a binary field into a Base64 string.
Ok, this helps. As #Casey say:
Linq to Entities doesn't recognize .ToString() calls; it doesn't know how to convert these into SQL. However, you can run that in memory; simply resolve the objects (call .ToList() or something) and then perform the select statement on the in-memory objects. It'll be Linq to Objects and that'll be permitted.
I tried it on my code and it works. What i done ? I first call ToList() method whenever i getting data from database, and then perform the operations.
This code works fine...
List<NarudzbeVM> narudzbe = db.Narudzbe.Where(x => x.KupacID == id).ToList().
Select(x => new NarudzbeVM()
{
BrojNarudzbe = x.BrojNarudzbe,
Datum = x.Datum,
KupacID = x.KupacID,
NarudzbaID = x.NarudzbaID,
Otkazano = x.Otkazano,
Status = x.Status,
StavkeNarudzbe = db.NarudzbaStavke.Where(y => y.NarudzbaID == x.NarudzbaID).ToList().
Select(z => new NarudzbaStavkeVM()
{
Kolicina = z.Kolicina,
NarudzbaID = z.NarudzbaID,
NarudzbaStavkaID = z.NarudzbaStavkaID,
ProizvodID = z.ProizvodID,
Proizvod = db.Proizvodi.Where(k => k.ProizvodID == z.ProizvodID).ToList().
Select(t => new ProizvodTest()
{
Cijena = t.Cijena,
ProizvodID = t.ProizvodID,
JedinicaMjere = t.JediniceMjere.Naziv,
VrstaProizvoda = t.VrsteProizvoda.Naziv,
Naziv = t.Naziv,
Sifra = t.Sifra,
SlikaThumb = Convert.ToBase64String(t.SlikaThumb),
}).FirstOrDefault()
}).ToList()
}).ToList();
try with this
string yourString= System.Text.Encoding.Default.GetString(
System.Text.Encoding.Default.GetBytes(yorbyteArray));
I am trying to filter my linq query, using distinct() method but I keep getting all the data records (including duplication). I have tried the following variations, which all seem to be failing.
int total = Data.Count();
// Data = Data.GroupBy(member => member.Tag).Select(x => x.OrderBy(y => y.Name).First());
// Data = Data.OrderByDescending(c => c.UploadDate);
Data = Data.Distinct().OrderBy(value => value.Tag);
var data = Data.ToList();
How can I filter my query by showing all the data fieldnames which are filtered by unique tags field name? My tag fieldname does contain NULL data as well.
Here is my entire method, for further reference:
[Authorize]
[HttpPost]
private HttpResponseMessage method(HttpContext request, Query query)
{
if (User.IsInRole("admin") || User.IsInRole("art"))
{
IQueryable<database_B> Data = null;
if (!string.IsNullOrEmpty(query.name))
{
var ids = query.name.Split(',');
// var dataMatchingTags = db.database_B.Where(c => ids.Any(id => c.Name.Contains(id)));
if (Data == null)
Data = dataMatchingTags;
else
Data = Data.Union(dataMatchingTags);
}
if (Data == null) // If no tags or name is being queried, apply filters to the whole set of products
Data = db.database_B;
if (query.endDate != null)
{
Data = Data.Where(c => c.UploadDate <= query.endDate);
}
if (query.startDate != null)
{
Data = Data.Where(c => c.UploadDate >= query.startDate);
}
int total = Data.Count();
// Data = Data.GroupBy(member => member.Tag).Select(x => x.OrderBy(y => y.Name).First());
// Data = Data.OrderByDescending(c => c.UploadDate);
Data = Data.Distinct().OrderBy(value => value.Tag);
var data = Data.ToList();
if (!data.Any())
{
var message = string.Format("No data found");
return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
}
// return Request.CreateResponse(HttpStatusCode.OK, data);
return Request.CreateResponse(HttpStatusCode.OK, new { total, data });
}
Thank you for any further help.
You need something like that ?
http://www.codeproject.com/Articles/535374/DistinctBy-in-Linq-Find-Distinct-object-by-Propert
If database_B is a class (as opposed to a struct) which does not implement IEquatable<database_B> in a suitable way, Distinct will treat different objects as different, regardless of member values. A possible solution would be to implementet IEquatable<database_B> to reflect the comparision which is desired for equality.
Alternatively, a different overload of Distinct can be used, where it is possible to give a custom comparision as an argument.
Your class database_B has to implement Equals- and GetHashCode-Method in order to tell the Distinct under which circumstances two instances are considered equal and may therefor be filtered out.
I don't know if the question is properly formatted but what I'm trying to do is to create the var reservations outside the using loop but don't know how to initialize it.
This code works :
using (MainContextDB db = new MainContextDB())
{
var reservations = (from c in db.Reservations select new { c.CustAcctNo, c.ReservNo, c.ReservStatus }).ToList();
}
Any attempt to declare the var outside the loop will trigger an error:
Cannot convert List to List
I've tried:
var reservations = new List<dynamic>();
var reservations = new List<object>();
This code works, but requires to retrieve all columns, which is not what I want:
List<Reservation> reservations = new List<Reservation>();
using (MainContextDB db = new MainContextDB())
{
reservations = db.Reservations.ToList();
}
You could do it this way:
var reservations = new []
{
new { CustAcctNo = "", ReservNo = "", ReservStatus = "" }
}.ToList();
using (MainContextDB db = new MainContextDB())
{
reservations = (
from c in db.Reservations
select new
{
c.CustAcctNo, c.ReservNo, c.ReservStatus
}).ToList();
}
You just have to make sure you match the types on the members of your anonymous class.
The other option is to add a reference to the Microsoft Reactive Framework Team's "Interactive Extensions". They have a nice Using method for enmerables that lets you do this:
var reservations =
EnumerableEx
.Using(
() => new MainContextDB(),
db =>
from c in db.Reservations
select new
{
c.CustAcctNo, c.ReservNo, c.ReservStatus
})
.ToList();
Ok that ended up being a really interesting question-
I know that anonymous types aren't supposed to leave the method context, hadn't really thought about them leaving scope though...
I see a few possible options...
Do something hackey - Two anon types with the same signature share the same type, so you could coerce it into accepting a prototype and go from there. (converting into a list is difficult but doable in generics... see the link posted by simo)
Move the operations into your using context which I know isn't ideal
Manually dispose the context
Handle the items as dynamic
You could substitute a custom type or a tuple for the anonymous type
Hope that helps, I'm somewhat suprised there isn't a straightforward way to do this if you are remaining inside a method scope.
Note: I would use none of the below approaches in performance-sensitive code.
Having said that, I am seeing a very simple solution here which can also be applied when you're dealing with types other than List<T>. A bit of type inference gets the job done:
private T InvokeAndReturn<T>(Func<T> func)
{
return func();
}
Usage:
// reservations is List<'a>.
var reservations = this.InvokeAndReturn(() =>
{
using (var db = new MainContextDB())
{
return db.Reservations
.Select(c => new { c.CustAcctNo, c.ReservNo, c.ReservStatus })
.ToList();
}
});
Fresh edit
Just had to use this in my own code and opted for an IDisposable-aware alternative instead:
TReturn Using<TDisposable, TReturn>(TDisposable disposable, Func<TDisposable, TReturn> func)
where TDisposable : IDisposable
{
try
{
return func(disposable);
}
finally
{
if (disposable != null)
{
disposable.Dispose();
}
}
}
Usage:
var reservations = Using(new MainContextDB(), db =>
{
return db.Reservations
.Select(c => new { c.CustAcctNo, c.ReservNo, c.ReservStatus })
.ToList();
});
Or an even shorter version
var reservations = Using(new MainContextDB(), db =>
db.Reservations
.Select(c => new { c.CustAcctNo, c.ReservNo, c.ReservStatus })
.ToList()
);
I am having trouble creating an extension method for an IQueryable that will include the translation for a specified column in a Linq Query.
Suppose i have the query below.
I would like to call a method IncludeTranslation on the CFG_Article IQueryable specifying the column i want to get the translation for.
Could someone help me in the right direction.
var translations =
from t in UoW.CFG_TRANSLATION.GetAll()
select t;
var result = (
from a in UoW.CFG_ARTICLE.GetAll()
select new
{
a,
translation = translations
.Where(t=> t.TR_TEXT == a.AR_NAME).FirstOrDefault()
});
All i have come up so far is the code below but this does not compile.
public static IQueryable IncludeTranslation<T>(
this IQueryable<T> query,
Expression<Func<t, bool>> fieldToTranslate)
{
// this will get an IQueryable of CFG_TRANSLATION
var translations = GetTranslations();
var result = (
from q in query
select new
{
q,
translation = translations
.Where(t=> t.TR_TEXT == fieldToTranslate)
.FirstOrDefault()
});
// even better is to return all fields from query
// + the TR_TRANSLATION field from the translations table
return result;
}
Try this (I'm having to guess class names are CFG_ARTICLE & CFG_TRANSLATION - replace as required)
public static IQueryable IncludeTranslation(
this IQueryable<CGF_ARTICLE> query,
Func<CFG_ARTICLE, CFG_TRANSLATION, bool> fieldToTranslate)
{
var translations = GetTranslations();
var result =
from a in query
select new
{
a,
translation = translations
.Where(t => fieldToTranslate(a, t))
.FirstOrDefault()
};
return result;
}
calling like this
var result = query.IncludeTranslation(
(article, translation) => article.TR_TEXT == translation.AR_NAME);
I found an other way of returning the same result using a Generic Way.
public static IQueryable IncludeTranslation<S>(this IQueryable<S> source, Expression<Func<S, string>> keyField)
where S : class
{
IQueryable<CFG_TRANSLATION> translations = GetTranslations();
var trans = source.GroupJoin(translations, keyField, t => t.TR_TEXT, (s, t) => new { Source = s, Translations = t });
var result = trans.Select(t => new {
Source = t.Source,
Translation = t.Translations
.FirstOrDefault()
});
return result;
}
Maybe someone can use this as a sollution
this can be called as follow
var Result = QueryableTable.IncludeTranslation(t => t.FieldToTranslate);
Is there any way to reduce the following code into Linq form?
foreach (var current in currentWhiteListApps)
{
var exists = false;
foreach (var whiteList in clientSideWhiteLists)
{
if (current.appID.Equals(whiteList.appID))
{
exists = true;
}
}
if (!exists)
{
deleteList.Add(current);
}
}
All I can think of is:
currentWhiteListApps.Select(x => {
var any = clientSideWhiteLists.Where(y => y.appID.Equals(x.appID));
if (any.Any())
deleteList.AddRange(any.ToArray());
return x;
});
Reason For LINQ
LINQ is far more readable than nested foreach loops, and requires less code. So this is the reason I would like it in LINQ
var deleteList = currentWhiteListApps.Where(x =>
clientSideWhiteLists.All(y => !x.appID.Equals(y.appID)))
.ToList();
var deleteList = currentWhiteListApps.Except(clientSideWhiteLists).ToList();
This solution assumes that both collections contains elements of the same type and this type has overriden Equals() that compares appID.
var validIds = new HashSet<int>(clientSideWhiteLists.Select(x => x.appId));
var deleteList = currentWhiteListApps.Where(x => !validIds.Contains(x.appId)).ToList();