How to convert ReversedRandomAccessCollection to regular collection - sorting

I've been trying to find a way to sort my resulting MPMediaQuery so that the results are sorted by date.
I've had a lot of difficulty, and then I found the "reversed()" method, but I cannot get the returned data into a format that I can use with the MPMediaPlayer.
My original query:
var qryPodcasts = MPMediaQuery()
var titleFilter = MPMediaPropertyPredicate()
titleFilter = MPMediaPropertyPredicate(value: "This American Life", forProperty: MPMediaItemPropertyPodcastTitle, comparisonType: .equalTo)
qryPodcasts.addFilterPredicate(titleFilter)
So I tried this:
let myItems = qryPodcasts.items?.reversed()
podCollection = MPMediaItemCollection(items: myItems!) //ERROR HERE
myMP.setQueue(with: podCollection!)
Which gave me this error:
"Cannot convert value of type 'ReversedRandomAccessCollection<[MPMediaItem]>' (aka 'ReversedRandomAccessCollection<Array<MPMediaItem>>') to expected argument type '[MPMediaItem]'"
How can I use the results of 'reversed()' in the MediaPlayer?

what about this?
let myItems = qryPodcasts.items?.reversed()
podCollection = MPMediaItemCollection(items: Array(myItems)!)
myMP.setQueue(with: podCollection!)

Related

Linq Query Message: Specified cast is not valid

Following are the columns name and its data type:
TemplateName string
TaskName string
AvgDays string (but contains int values)
my LINQ query:
DataTable newTable = new DataTable();
newTable = (from r in table.AsEnumerable()
group r by r.Field<string>("TemplateName") into templates
let totalDays = templates.Sum(r => r.Field<int>("AvgDays"))
from t in templates
group t by new
{
TemplateName = templates.Key,
TaskName = t.Field<string>("TaskName"),
TotalDays = totalDays
} into tasks
select new
{
tasks.Key.TemplateName,
tasks.Key.TaskName,
AvgDays = tasks.Sum(r => r.Field<int>("AvgDays")),
tasks.Key.TotalDays
}).CopyToDataTable();
I am getting error after execution of query. Error is "Specified cast is not valid.".
Please let me know where am I doing wrong.
I guess Field<int> causes the problem, because the field is not really an int. As you said before, it's a string.
Try following
AvgDays = tasks.Sum(r => int.Parse(r.Field<string>("AvgDays"))),
Field<T> does not perform some magic transformation between different types. It's implemented like that:
return (T)((object)value);
In practice there is a little bit more code, but logic is the same. It just tried to cast your value to desired type, and as you probably know, casting string to int does not work.

LINQ and dynamic strong types

I try to find some references on LINQ with dynamic added strong types, static I have as in example:
var rowColl = _data.AsEnumerable();
var json = (from r in rowColl
select new
{
name = r.Field<string>("name"),
id = r.Field<int>("id"),
}).ToList();
Now where I am interested in if its possible to make "name" and "id" dynamic added on runtime as the information is available in the DataTable "_data", I think there is a simple solution for this however cant find any references on this
It's better practice to avoid using "var" as your type when possible. It looks like rowColl is of type IEnumerable<DataRow>. If that's true, then I would look to see what you can use in the DataRow class (see msdn documentation).
Given that rowColl is actually IEnumerable<DataRow>... If the columns are always going to be in the same order, then you could just do something like r[0] and r[1] in your select statement, i.e.
var json = (from r in rowColl
select new
{
name = r[0], // Where 0 is the index of the "name" column
id = r[1],
}).ToList();
If it complains at you for type-safety, then you could use int.Parse() to cast the string to an int and use the .ToString() extension on your columns instead.

Unable to create a constant value - only primitive types or Enumeration types allowed

I have seen some questions related to this Exception here but none made me understand the root cause of the problem. So here we have one more...
var testquery =
((from le in context.LoanEMIs.Include("LoanPmnt")
join lp in context.LoanPmnts on le.Id equals lp.LoanEMIId
where lp.PmntDtTm < date && lp.IsPaid == false
&& le.IsActive == true && lp.Amount > 0
select new ObjGetAllPendingPmntDetails
{
Id = lp.Id,
Table = "LoanEMI",
loanEMIId = lp.LoanEMIId,
Name = le.AcHead,
Ref = SqlFunctions.StringConvert((double)le.FreqId),
PmntDtTm = lp.PmntDtTm,
Amount = lp.Amount,
IsDiscard = lp.IsDiscarded,
DiscardRemarks = lp.DiscardRemarks
}).DefaultIfEmpty(ObjNull));
List<ObjGetAllPendingPmntDetails> test = testquery.ToList();
This query gives the following Exception Message -
Unable to create a constant value of type CashVitae.ObjGetAllPendingPmntDetails. Only primitive types or enumeration types are supported in this context.
I got this Exception after I added the SQL function statement to convert le.FreqId which is a byte to a string as ToString() is not recognized in the LINQ Expression Store.
ObjGetAllPendingPmntDetails is a partial class in my model which is added as it is used too many times in the code to bind data to tables.
It has both IDs as long, 'Amount' as decimal, PmntDtTm as Datetime,IsDiscard as bool and remaining all are string including 'Ref'.
I get no results as currently no data satisfies the condition. While trying to handle null, I added DefaultIfEmpty(ObjNull) and ObjNull has all properties initialized as follows.
ObjGetAllPendingPmntDetails ObjNull = new ObjGetAllPendingPmntDetails()
{ Id = 0, Table = "-", loanEMIId = 0, Name = "-", Ref = "-",
PmntDtTm = Convert.ToDateTime("01-01-1900"),
Amount = 0, IsDiscard = false, DiscardRemarks = "" };
I need this query to work fine as it has Union() called on it with 5 other queries. All returning the same ObjGetAllPendingPmntDetails columns. But there is some problem as this query has no data satisfying the conditions and the Exception Shared Above.
Any suggestions are appreciated as I am unable to understand the root cause of the problem.
#AndrewCoonce is right, the .DefaultIfEmpty(ObjNull) is the culprit here. Entity Framework turns DefaultIfEmpty into something like...
CASE WHEN ([Project1].[C1] IS NULL) THEN #param ELSE [Project1].[Value] END AS [C1]
...but there's no way to coerce an instance of ObjGetAllPendingPmntDetails into something that can take the place of #param, so you get an exception.
If you move the DefaultIfEmpty call to after the ToList it should work correctly (although you'll need to call ToList again after that if you really want a concrete list instance).

how to convert Anonymous type to int

I am using linq query in that i need all the values so first i am using linq query and
after that i am taking all values in one List like this
var lst = ProjectContext.My_prj_project.Select(i => new
{
Name = list
}).Distinct().FirstOrDefault();
ProjectReportDetailsModels l = new ProjectReportProjectCategoryDetailsModels();
l.name= lst.Name; // here i am getting error
connot implicitly convert 'AnonymousType#1' to 'int'
So please send me any sample, example (or) related link
Thanks in Advance.
This may help you
l.name = lst.Select(x=>x.Name);
you are getting a list in lst ? then why you are doing FirstOrDefault() ?
l.name = lst.Select(x=>x.Name).FirstOrDefault();
will solve the problem but i really cannot comprehend what you are doing ...

LINQ query returning null results

I have the following code
nodes = data.Descendants(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Results")).Nodes();
System.Collections.Generic.IEnumerable<Result> res = new List<Result>();
if (nodes.Count() > 0)
{
var results = from uris in nodes
select new Result
{
URL =
((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Url")).Value,
Title =
((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Title")).Value,
Description =
((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Description")).Value,
DateTime =
((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}DateTime")).Value,
};
res = results;
}
Where Results is a object who has those URL, Title, Description, and DateTime variables defined.
This all works fine normally, but when a 'node' in nodes doesnt contain a Description element (or at least I think thats whats throwing it) the program hits the "res = results;"
line of code and throws a 'object reference not set to...' error and highlights the whole section right after "select new Results"..
How do I fix this?
The simplest way is to cast to string instead of using the Value property. That way you'll end up with a null reference for the Description instead.
However, your code can also be made a lot nicer:
XNamespace ns = "http://schemas.microsoft.com/LiveSearch/2008/04/XML/web";
var results = data.Descendants(ns + "Results")
.Elements()
.Select(x => new Result
{
URL = (string) x.Element(ns + "Url"),
Title = (string) x.Element(ns + "Title"),
Description = (string) x.Element(ns + "Description"),
DateTime = (string) x.Element(ns + "DateTime")
})
.ToList();
See how much simpler that is? Techiques used:
Calling ToList() on an empty sequence gives you a list anyway
This way you'll only ever perform the query once; before you were calling Count() which would potentially have iterated over each node. In general, use Any() instead of Count() > 0) - but this time just making the list unconditional is simpler.
Use the Elements() method to get child elements, rather than casting multiple times. (Your previous code would have thrown an exception if it had encountered any non-element nodes)
Use the implicit conversion from string to XNamespace
Use the +(XNamespace, string) operator to get an XName
If the Description element is not included you should test if this
((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Description"))
is not null before using Value. Try this code:
var results = from uris in nodes let des = ((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Description"))
select new Result
{
URL = ((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Url")).Value,
Title = ((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}Title")).Value,
Description = (des != null) ? des.Value : string.Empty,
DateTime = ((XElement)uris).Element(XName.Get("{http://schemas.microsoft.com/LiveSearch/2008/04/XML/web}DateTime")).Value,
};

Resources