I have an object as follows,
public class Foo
{
public Dictionary<string, List<double?>> Bar { get; set; }
}
I serialize using, string myJson = JsonConvert.Serialize(myFoo) and get sensible Json. However when I run JsonConvert.Deserialize<Foo>(myJson) I get an ArgumentException Parameter name: value.
Why is this?
I am using Json.Net on a Windows Phone 7.1 project.
Edit: Here is an example object and the Json it produces,
Foo myFoo = new Foo()
{
Bar = new Dictionary<string,List<double?>>() {
{"Flim", new List<double?>() { 0, 0.2, null, 0.9 }},
{"Flam", new List<double?>() { 0.0,0.1, null, null}},
}
};
The contents of myJson after serialization (double quote escapes removed)
{"Bar":{"Flim":[0.0,0.2,null,0.9],"Flam":[0.0,0.1,null,null]}}
It worked fine for me using Json.Net 4.5.11 on .NET 4.5 in standard Windows. Here is the program I used (below). Can you try running this exact code in your environment and see if it works? If so, then your ArgumentException must be coming from somewhere else. If not, then that seems to point to a difference between Windows and Windows Phone environments.
class Program
{
static void Main(string[] args)
{
Foo myFoo = new Foo()
{
Bar = new Dictionary<string, List<double?>>()
{
{ "Flim", new List<double?>() { 0, 0.2, null, 0.9 } },
{ "Flam", new List<double?>() { 0.0, 0.1, null, null } },
}
};
string json = JsonConvert.SerializeObject(myFoo);
Console.WriteLine(json);
Foo foo2 = JsonConvert.DeserializeObject<Foo>(json);
foreach (KeyValuePair<string, List<double?>> kvp in foo2.Bar)
{
Console.Write(kvp.Key);
Console.Write(":");
string sep = " {";
foreach (double? d in kvp.Value)
{
Console.Write(sep);
Console.Write(d.HasValue ? d.Value.ToString() : "null");
sep = ", ";
}
Console.WriteLine("}");
}
}
public class Foo
{
public Dictionary<string, List<double?>> Bar { get; set; }
}
}
Output:
{"Bar":{"Flim":[0.0,0.2,null,0.9],"Flam":[0.0,0.1,null,null]}}
Flim: {0, 0.2, null, 0.9}
Flam: {0, 0.1, null, null}
I create this class for a test.
I want to compare to List of the class and get different class between ListA and ListB. In my example the result get only class of ListB.
I do the same thin with list of string and work it
Class Example
public class FileNode
{
public string Source { get; set; }
public int Id { get; set; }
}
List<FileNode> ListA = new List<FileNode>
{
new FileNode{ Id = 1, Source="a" },
new FileNode{ Id = 2, Source="b" },
};
List<FileNode> ListB = new List<FileNode>
{
new FileNode{ Id = 1, Source="a" },
new FileNode{ Id = 2, Source="b" },
new FileNode{ Id = 3, Source="c" },
};
List<FileNode> ListAB = ListB.Where(m => !ListA.Contains(m)).ToList();
String example, it's works
List<string> a = new List<string> {"a","b","c","d","e" };
List<string> b = new List<string> {"a","b","c","d" };
List<string> ab = a.Where(m => !b.Contains(m)).ToList();
Well Contains is going to call Equals on the elements - and may also use GetHashCode (I doubt it, but you should override it consistently anyway). So you need to override Equals(object) and GetHashCode() in FileNode. (By default, you'll get reference equality.)
Note that as soon as you start trying to use Contains in a query which will execute in the database, it could behave completely different - it wouldn't be looking at your Equals/GetHashCode methods at that point.
I'm trying to bind an enum AgeRange using Html.DropDownListFor but regardless of whatever I'm choosing from View page, Controller is getting a value '0'. Can anyone help me to fix this issue?
EDIT: Controller code in place.
Enum Class:
public enum AgeRange
{
Unknown = -1,
[Description("< 3 days")]
AgeLessThan3Days = 1,
[Description("3-6 days")]
AgeBetween3And6 = 2,
[Description("6-9 days")]
AgeBetween6And9 = 3,
[Description("> 9 days")]
AgeGreaterThan9Days = 4
}
View:
#Html.DropDownListFor(
model => model.Filter.AgeRangeId,
#Html.GetEnumDescriptions(typeof(AgeRange)),
new { #class = "search-dropdown", name = "ageRangeId" }
)
Controller:
public ActionResult Search(int? ageRangeId)
{
var filter = new CaseFilter { AgeRangeId = (AgeRange)(ageRangeId ?? 0) };
}
You're close...
I'd suggest following along with this guy
You have to write an extension method for your selectlist to work.
I use this
public static SelectList ToSelectList<TEnum>(this TEnum enumeration) where TEnum : struct
{
//You can not use a type constraints on special class Enum.
if (!typeof(TEnum).IsEnum)
throw new ArgumentException("TEnum must be of type System.Enum");
var source = Enum.GetValues(typeof(TEnum));
var items = new Dictionary<object, string>();
foreach (var value in source)
{
FieldInfo field = value.GetType().GetField(value.ToString());
DisplayAttribute attrs = (DisplayAttribute)field.GetCustomAttributes(typeof(DisplayAttribute), false).First();
items.Add(value, attrs.GetName());
}
return new SelectList(items, Constants.PropertyKey, Constants.PropertyValue, enumeration);
}
Given the following code:
public class RMAInfo
{
public enum RMAStatuses {
Undefined = 0, Approved = 1, Denied = 2,
Pending = 3, Received = 4, Closed = 5
}
public enum ReturnLocations { Undefined = 0, Utah = 1, Indy = 2 }
public RMAInfo()
{
ID = -1;
RMACode = string.Empty;
}
public int ID { get; set; }
public string RMACode { get; set; }
public string ResellerID { get; set; }
public RMAStatuses RMAStatus { get; set; }
}
private List<RMAInfo> GetRMAInfos_Internal(string resellerID)
{
List<RMAInfo> returnRMAInfos = new List<RMAInfo>();
using (Models.RMAEntities context = new Models.RMAEntities())
{
returnRMAInfos = (from r in context.RMAs
where r.ResellerID == resellerID
select new RMAInfo
{
ID = r.ID,
RMACode = r.RMACode,
ResellerID = r.ResellerID,
// error on next line!
RMAStatus = RMAInfo.RMAStatuses.Pending
}).ToList();
}
return returnRMAInfos;
}
I am getting an error on the assignment to the RMAStatus field. The error is
The specified value is not an instance of type 'Edm.Int32'
If I comment out that line, it works fine.
I have also tried to do this same code without using EF, and it seems to work fine.
Any ideas?
Entity Framework does not like the enum, as it cannot translate it to SQL. You would need to expose a way for EF to set the underlying int value, or you would have to set the value yourself once EF was done with it.
What you might do is expose an int property to set it. If you wish, you could restrict it to internal access so that perhaps callers can't see it but your EF code can (assuming callers are in different assemblies, but your context is not). Then you could have
public class RMAInfo
{
///<summary>
/// Integer representation of RMAStatus
///</summary>
internal int RMAStatusCode
{
get { return (int)this.RMAStatus; } // you could omit the getter
set { this.RMAStatus = (RMAInfo.RMAStatuses)value; }
}
}
...
select new RMAInfo
{
...
RMAStatusCode = (int)RMAInfo.RMAStatuses.Pending
}
To avoid this, you would basically select your RMAInfo sans status, and then iterate over the result to set each status to pending, leaving EF out of it entirely.
Installing .Net 4.5 appears to fix the issue as well (your project can still be on 4.0).
I was having this issue on our staging server (dev and test servers worked fine) and discovered that it did not have .Net 4.5 installed. Once I installed 4.5, the issue cleared up without any code changes.
I'm trying to prepare data for a graph using LINQ.
The problem that i cant solve is how to calculate the "difference to previous.
the result I expect is
ID= 1, Date= Now, DiffToPrev= 0;
ID= 1, Date= Now+1, DiffToPrev= 3;
ID= 1, Date= Now+2, DiffToPrev= 7;
ID= 1, Date= Now+3, DiffToPrev= -6;
etc...
Can You help me create such a query ?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public class MyObject
{
public int ID { get; set; }
public DateTime Date { get; set; }
public int Value { get; set; }
}
class Program
{
static void Main()
{
var list = new List<MyObject>
{
new MyObject {ID= 1,Date = DateTime.Now,Value = 5},
new MyObject {ID= 1,Date = DateTime.Now.AddDays(1),Value = 8},
new MyObject {ID= 1,Date = DateTime.Now.AddDays(2),Value = 15},
new MyObject {ID= 1,Date = DateTime.Now.AddDays(3),Value = 9},
new MyObject {ID= 1,Date = DateTime.Now.AddDays(4),Value = 12},
new MyObject {ID= 1,Date = DateTime.Now.AddDays(5),Value = 25},
new MyObject {ID= 2,Date = DateTime.Now,Value = 10},
new MyObject {ID= 2,Date = DateTime.Now.AddDays(1),Value = 7},
new MyObject {ID= 2,Date = DateTime.Now.AddDays(2),Value = 19},
new MyObject {ID= 2,Date = DateTime.Now.AddDays(3),Value = 12},
new MyObject {ID= 2,Date = DateTime.Now.AddDays(4),Value = 15},
new MyObject {ID= 2,Date = DateTime.Now.AddDays(5),Value = 18}
};
Console.WriteLine(list);
Console.ReadLine();
}
}
}
One option (for LINQ to Objects) would be to create your own LINQ operator:
// I don't like this name :(
public static IEnumerable<TResult> SelectWithPrevious<TSource, TResult>
(this IEnumerable<TSource> source,
Func<TSource, TSource, TResult> projection)
{
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
{
yield break;
}
TSource previous = iterator.Current;
while (iterator.MoveNext())
{
yield return projection(previous, iterator.Current);
previous = iterator.Current;
}
}
}
This enables you to perform your projection using only a single pass of the source sequence, which is always a bonus (imagine running it over a large log file).
Note that it will project a sequence of length n into a sequence of length n-1 - you may want to prepend a "dummy" first element, for example. (Or change the method to include one.)
Here's an example of how you'd use it:
var query = list.SelectWithPrevious((prev, cur) =>
new { ID = cur.ID, Date = cur.Date, DateDiff = (cur.Date - prev.Date).Days) });
Note that this will include the final result of one ID with the first result of the next ID... you may wish to group your sequence by ID first.
Use index to get previous object:
var LinqList = list.Select(
(myObject, index) =>
new {
ID = myObject.ID,
Date = myObject.Date,
Value = myObject.Value,
DiffToPrev = (index > 0 ? myObject.Value - list[index - 1].Value : 0)
}
);
In C#4 you can use the Zip method in order to process two items at a time. Like this:
var list1 = list.Take(list.Count() - 1);
var list2 = list.Skip(1);
var diff = list1.Zip(list2, (item1, item2) => ...);
Modification of Jon Skeet's answer to not skip the first item:
public static IEnumerable<TResult> SelectWithPrev<TSource, TResult>
(this IEnumerable<TSource> source,
Func<TSource, TSource, bool, TResult> projection)
{
using (var iterator = source.GetEnumerator())
{
var isfirst = true;
var previous = default(TSource);
while (iterator.MoveNext())
{
yield return projection(iterator.Current, previous, isfirst);
isfirst = false;
previous = iterator.Current;
}
}
}
A few key differences... passes a third bool parameter to indicate if it is the first element of the enumerable. I also switched the order of the current/previous parameters.
Here's the matching example:
var query = list.SelectWithPrevious((cur, prev, isfirst) =>
new {
ID = cur.ID,
Date = cur.Date,
DateDiff = (isfirst ? cur.Date : cur.Date - prev.Date).Days);
});
Further to Felix Ungman's post above, below is an example of how you can achieve the data you need making use of Zip():
var diffs = list.Skip(1).Zip(list,
(curr, prev) => new { CurrentID = curr.ID, PreviousID = prev.ID, CurrDate = curr.Date, PrevDate = prev.Date, DiffToPrev = curr.Date.Day - prev.Date.Day })
.ToList();
diffs.ForEach(fe => Console.WriteLine(string.Format("Current ID: {0}, Previous ID: {1} Current Date: {2}, Previous Date: {3} Diff: {4}",
fe.CurrentID, fe.PreviousID, fe.CurrDate, fe.PrevDate, fe.DiffToPrev)));
Basically, you are zipping two versions of the same list but the first version (the current list) begins at the 2nd element in the collection, otherwise a difference would always differ the same element, giving a difference of zero.
I hope this makes sense,
Dave
Yet another mod on Jon Skeet's version (thanks for your solution +1). Except this is returning an enumerable of tuples.
public static IEnumerable<Tuple<T, T>> Intermediate<T>(this IEnumerable<T> source)
{
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
{
yield break;
}
T previous = iterator.Current;
while (iterator.MoveNext())
{
yield return new Tuple<T, T>(previous, iterator.Current);
previous = iterator.Current;
}
}
}
This is NOT returning the first because it's about returning the intermediate between items.
use it like:
public class MyObject
{
public int ID { get; set; }
public DateTime Date { get; set; }
public int Value { get; set; }
}
var myObjectList = new List<MyObject>();
// don't forget to order on `Date`
foreach(var deltaItem in myObjectList.Intermediate())
{
var delta = deltaItem.Second.Offset - deltaItem.First.Offset;
// ..
}
OR
var newList = myObjectList.Intermediate().Select(item => item.Second.Date - item.First.Date);
OR (like jon shows)
var newList = myObjectList.Intermediate().Select(item => new
{
ID = item.Second.ID,
Date = item.Second.Date,
DateDiff = (item.Second.Date - item.First.Date).Days
});
Here is the refactored code with C# 7.2 using the readonly struct and the ValueTuple (also struct).
I use Zip() to create (CurrentID, PreviousID, CurrDate, PrevDate, DiffToPrev) tuple of 5 members. It is easily iterated with foreach:
foreach(var (CurrentID, PreviousID, CurrDate, PrevDate, DiffToPrev) in diffs)
The full code:
public readonly struct S
{
public int ID { get; }
public DateTime Date { get; }
public int Value { get; }
public S(S other) => this = other;
public S(int id, DateTime date, int value)
{
ID = id;
Date = date;
Value = value;
}
public static void DumpDiffs(IEnumerable<S> list)
{
// Zip (or compare) list with offset 1 - Skip(1) - vs the original list
// this way the items compared are i[j+1] vs i[j]
// Note: the resulting enumeration will include list.Count-1 items
var diffs = list.Skip(1)
.Zip(list, (curr, prev) =>
(CurrentID: curr.ID, PreviousID: prev.ID,
CurrDate: curr.Date, PrevDate: prev.Date,
DiffToPrev: curr.Date.Day - prev.Date.Day));
foreach(var (CurrentID, PreviousID, CurrDate, PrevDate, DiffToPrev) in diffs)
Console.WriteLine($"Current ID: {CurrentID}, Previous ID: {PreviousID} " +
$"Current Date: {CurrDate}, Previous Date: {PrevDate} " +
$"Diff: {DiffToPrev}");
}
}
Unit test output:
// the list:
// ID Date
// ---------------
// 233 17-Feb-19
// 122 31-Mar-19
// 412 03-Mar-19
// 340 05-May-19
// 920 15-May-19
// CurrentID PreviousID CurrentDate PreviousDate Diff (days)
// ---------------------------------------------------------
// 122 233 31-Mar-19 17-Feb-19 14
// 412 122 03-Mar-19 31-Mar-19 -28
// 340 412 05-May-19 03-Mar-19 2
// 920 340 15-May-19 05-May-19 10
Note: the struct (especially readonly) performance is much better than that of a class.
Thanks #FelixUngman and #DavidHuxtable for their Zip() ideas!