Unable to cast a list - c#

I am getting a error in the line below.
temp.day1_veh_p = string.Join(Environment.NewLine, day1.Where(x => x.plannedTriips == 1).Select(x => new {value=x.vehicleNumber+":"+x.shiftCompletedOn }).Cast<string>().ToArray());
Th error Message being
Unable to cast object of type '<>f__AnonymousType0`1[System.String]' to type 'System.String'.
The list day1 is of type
public class tripDetails
{
public string accountID { get; set; }
public string supplierName { get; set; }
public string supplierCode { get; set; }
public DateTime shiftFrom { get; set; }
public DateTime shiftTo { get; set; }
public int plannedTriips { get; set; }
public int actualTrips { get; set; }
public DateTime forDate { get; set; }
public string vehicleNumber { get; set; }
public string shiftCompletedOn { get; set; }
public class Comparer : IEqualityComparer<tripDetails>
{
public bool Equals(tripDetails x, tripDetails y)
{
return x.supplierCode == y.supplierCode;
}
public int GetHashCode(tripDetails obj)
{
return (obj.supplierCode).GetHashCode();
}
}
}
What exactly Am i doing wrong??

The problem is the new { value = ... }
Replace:
Select(x => new {value=x.vehicleNumber+":"+x.shiftCompletedOn }).Cast<string>()
with
Select(x => x.vehicleNumber+":"+x.shiftCompletedOn)
and you're sorted. You won't need the Cast<string>() at all.
Your original code creates, for each record, a new instance of an anonymous type that has a member called value with the string desired; the second version just creates the string.
In a way, it is no different to trying this:
class Foo
{
public string Bar {get;set;}
}
...
var foo = new Foo { Bar = "abc" };
string s = (string)foo; // doesn't compile

Yes, an anonymous type is not a string, so replace this
.Select(x => new { value = x.vehicleNumber + ":" + x.shiftCompletedOn })
with
.Select(x => x.vehicleNumber + ":" + x.shiftCompletedOn)
Then you can use the query(you don't need to create a new array) for string.Join.
It's also helpful to use multiple lines, it makes your code much more readable:
var vehicles = day1.Where(x => x.plannedTriips == 1)
.Select(x => x.vehicleNumber + ":" + x.shiftCompletedOn);
string str = string.Join(Environment.NewLine, vehicles);

Replace this
(x => new {value=x.vehicleNumber+":"+x.shiftCompletedOn }).Cast<string>()
by this
(x => String.Format("{0}\:{1}", x.vehicleNumber, x.shiftCompletedOn))
When you are doing new { ... } you are creating items of anonymous type and then (Cast<string()) trying explicitly cast to string and such conversion is not defined - youn ends up with appropriate exception.

Related

How to turn an object into a request in C#

My Model, example:
public class Obj
{
public Obj()
{ }
public int? IdRestricao { get; set; }
public int? IdTipoRestringido { get; set; }
public string CodRestringido { get; set; }
public string NomeRestringido { get; set; }
public int? IdTipoRestricao { get; set; }
public string CodRestricao { get; set; }
public string NomeRestricao { get; set; }
public DateTime? PeriodoInicio { get; set; }
public DateTime? PeriodoFim { get; set; }
public int? IdStatus { get; set; }
}
Request
www.url.com.br?IdRestricao=1&IdTipoRestringido=2&CodRestringido=3&NomeRestringido=4&IdTipoRestricao=5&CodRestricao=6&NomeRestricao=7&PeriodoInicio=8&PeriodoFim=9
code:
var model = obj.*tostring()*//
something like
var request = new RestRequest($"/api/{**model**}", Method.GET);
edit1:
I'm wondering if there is a library or something that transforms my object in my request as in the examples above
You can override ToString to format the data from the Obj class into GET parameters.
You could write a utility function to convert all object properties into nameof and the associated value into key-value pairs.
Something such as this answer to convert your Obj into a dictionary, and then another method to convert the dictionary into Prop=value could be done.
For a one off something like this would be suitable:
public override string ToString()
{
return $"IdRestricao={IdRestricao}&IdTipoRestringido={IdTipoRestringido}&CodRestringido={CodRestringido}...
}
I found the answer to what I was looking for, it follows below in case anyone needs it in the future
private static string ToQueryString(this object request, string separator = ",")
{
if (request == null)
throw new ArgumentNullException("request");
// Get all properties on the object
var properties = request.GetType().GetProperties()
.Where(x => x.CanRead)
.Where(x => x.GetValue(request, null) != null)
.ToDictionary(x => x.Name, x => x.GetValue(request, null));
// Get names for all IEnumerable properties (excl. string)
var propertyNames = properties
.Where(x => !(x.Value is string) && x.Value is IEnumerable)
.Select(x => x.Key)
.ToList();
// Concat all IEnumerable properties into a comma separated string
foreach (var key in propertyNames)
{
var valueType = properties[key].GetType();
var valueElemType = valueType.IsGenericType
? valueType.GetGenericArguments()[0]
: valueType.GetElementType();
if (valueElemType.IsPrimitive || valueElemType == typeof(string))
{
var enumerable = properties[key] as IEnumerable;
properties[key] = string.Join(separator, enumerable.Cast<object>());
}
}
// Concat all key/value pairs into a string separated by ampersand
return string.Join("&", properties
.Select(x => string.Concat(
Uri.EscapeDataString(x.Key), "=",
Uri.EscapeDataString(x.Value.ToString()))));
}

cannot convert type decimal to double

I have a simple web service calling a sql view table through entity framework. I can bring all the columns in string fine but not the column in numeric like UID_NUM(numeric(38,8), null) in SQL. I have AddressALL class to set columns like below and error out at p.UID_NUM in LINQ.
public class GISAddressWebService : System.Web.Services.WebService
{
[WebMethod]
public AddressALL[] getAddress()
{
try
{
List<view_COBADDRESS> address = new List<view_COBADDRESS>();
using (GISAddressEntities database = new GISAddressEntities())
{
return database.view_COBADDRESS
.Where(p => p.UNIT_NUM == "103")
.Select(p => new AddressALL { UID_NUM = p.UID_NUM, ADD_FULL = p.ADD_FULL, POSTALCITY = p.POSTALCITY, ZIP5 = p.ZIP5}).ToArray();
}
}
catch (Exception)
{
return null;
}
}
}
public class AddressALL
{
public double UID_NUM { get; set; }
public string TLID { get; set; }
public string ADD_FULL { get; set; }
public string POSTALCITY { get; set; }
public string STATE { get; set; }
public string ZIP5 { get; set; }
public string IN_OUT { get; set; }
}
The decimal has more significant figures than the double, therefore it can be more precise and it also takes up slightly more memory. Because of this difference fou must explicitly program this change of type through (double)p.UID_NUM.
return database.view_COBADDRESS
.Where(p => p.UNIT_NUM == "103")
.Select(p => new AddressALL { UID_NUM = System.Convert.ToDouble(p.UID_NUM), ADD_FULL = p.ADD_FULL, POSTALCITY = p.POSTALCITY, ZIP5 = p.ZIP5}).ToArray();
MSDN
The obvious solution, instead of
.Select(p => new AddressALL
{
UID_NUM = p.UID_NUM,
ADD_FULL = p.ADD_FULL,
POSTALCITY = p.POSTALCITY,
ZIP5 = p.ZIP5
});
write
.Select(p => new AddressALL
{
UID_NUM = Convert.ToDouble(p.UID_NUM),
ADD_FULL = p.ADD_FULL,
POSTALCITY = p.POSTALCITY,
ZIP5 = p.ZIP5
});
In your select statement .Select(p => new AddressALL{ ... }) you are doing a projection that is trying to pick a new object of type AddressALL for each p, and you are using the object initializer syntax {...} to match the properties of your source objects p with the properties of your target type AddressALL.
Your error message however suggests your p.UID_NUM is of type decimal, while the UID_NUM property on your AddressALL is of type double. Therefore you have to convert the values to the necessary target type.

Implicitly Convert Type

i am doing this in WPF and i am using entity-framework .
this is my query code in my CRUD class file :
public class QuestionHint
{
public int? QuestionNo { get; set; } //change the type accordingly
public int? ActivityID { get; set; } //change the type accordingly
public int? TaskID { get; set; } //change the type accordingly
public string Answer { get; set; } //change the type accordingly
public string QuestionContent { get; set; } //change the type accordingly
public string joined { get; set; } //change the type accordingly
public string joinOption { get; set; } //change the type accordingly
}
public IList<QuestionHint> GetListKeys(int listTask, int listActivity)
{
IList<QuestionHint> lstRecords = context.questionhints.GroupBy(x => new { x.QuestionNo, x.ActivityID, x.TaskID }).ToList().Select(g => new QuestionHint()
{
QuestionNo = g.Key.QuestionNo,
ActivityID = g.Key.ActivityID,
TaskID = g.Key.TaskID,
joined = String.Join(" ",
g.OrderBy(q => q.questionhintID)
.Select(i => i.QuestionContent + "[" + i.Answer + "]")),
joinOption = String.Join(" ",
g.OrderBy(q => q.questionhintID)
.Select(a => "[" + a.Option1 + "," + a.Option2 + "]"))
}).Where(x => x.TaskID == listTask && x.ActivityID == listActivity)
//.Take(50)
.ToList();
return lstRecords;
}
i call this in code behind :
private DAO.DAOQuestionHint qh = new DAO.DAOQuestionHint();
public MainWindow2()
{
InitializeComponent();
PopulateQuestion(1, 5);
}
private void PopulateQuestion(int activityID, int taskID)
{
IList<QuestionHint> lstQuestionHints = qh.GetListKeys(taskID, activityID); // ERROR
//codes here...
}
i am getting this error in the code behind of my xaml.cs :
Cannot implicitly convert type
'System.Collections.Generic.IList'
to 'System.Collections.Generic.IList'. An
explicit conversion exists (are you missing a cast?)
iStellar is the name of the project. DAOQuestionHint is the name of the CRUD class file.
There is no error in the CRUD class file , i use the same query to retrieve records in the other project and it works well , don't know why it don't work in here.
You're using different capitalization for the generic argument in each example - IList<QuestionHint> in GetListKeys() and IList<Model.questionhint> in PopulateQuestion(). I'd guess these refer to similarly named but different types.

How to copy a List<> to another List<> with Comparsion in c#

I an having Two Lists. I want to get the matched and unmatched values based on ID and add the results to another List. I can get both of these using Intersect/Except.
But I can get only ID in the resultant variables (matches and unmatches) . I need all the properties in the Template.
List<Template> listForTemplate = new List<Template>();
List<Template1> listForTemplate1 = new List<Template1>();
var matches = listForTemplate .Select(f => f.ID)
.Intersect(listForTemplate1 .Select(b => b.ID));
var ummatches = listForTemplate .Select(f => f.ID)
.Except(listForTemplate1.Select(b => b.ID));
public class Template
{
public string ID{ get; set; }
public string Name{ get; set; }
public string Age{ get; set; }
public string Place{ get; set; }
public string City{ get; set; }
public string State{ get; set; }
public string Country{ get; set; }
}
public class Template1
{
public string ID{ get; set; }
}
If you don't want to implement IEquality for this simple task, you can just modify your LINQ queries:
var matches = listForTemplate.Where(f => listForTemplate1.Any(b => b.ID == f.ID));
and
var unmatches = listForTemplate.Where(f => listForTemplate1.All(b => b.ID != f.ID));
You might want to check for null before accessing ID, but it should work.
You are looking for the overloaded function, with the second parameter IEqualityComparer. So make your comparer ( example: http://www.blackwasp.co.uk/IEqualityComparer.aspx ), and use the same comparer in intersect / except.
And for the generic part: maybe you should have a common interface for templates e.g. ObjectWithID describing that the class have a string ID property. Or simply use dynamic in your comparer (but I think this is very-very antipattern because you can have run time errors if using for the bad type).
You also have a problem: intersecting two collections with two different types will result in a collection of Object (common parent class). Then you have to cast a lot (antipattern). I advise you to make a common abstract class/interface for your template classes, and it is working. If you need to cast the elements back, do not cast, but use the visitior pattern: http://en.wikipedia.org/wiki/Visitor_pattern
Example (good):
static void Main(string[] args)
{
// http://stackoverflow.com/questions/16496998/how-to-copy-a-list-to-another-list-with-comparsion-in-c-sharp
List<Template> listForTemplate = new Template[] {
new Template(){ID = "1"},
new Template(){ID = "2"},
new Template(){ID = "3"},
new Template(){ID = "4"},
new Template(){ID = "5"},
new Template(){ID = "6"},
}.ToList();
List<Template1> listForTemplate1 = new Template1[] {
new Template1(){ID = "1"},
new Template1(){ID = "3"},
new Template1(){ID = "5"}
}.ToList();
var comp = new ObjectWithIDComparer();
var matches = listForTemplate.Intersect(listForTemplate1, comp);
var ummatches = listForTemplate.Except(listForTemplate1, comp);
Console.WriteLine("Matches:");
foreach (var item in matches) // note that item is instance of ObjectWithID
{
Console.WriteLine("{0}", item.ID);
}
Console.WriteLine();
Console.WriteLine("Ummatches:");
foreach (var item in ummatches) // note that item is instance of ObjectWithID
{
Console.WriteLine("{0}", item.ID);
}
Console.WriteLine();
}
}
public class ObjectWithIDComparer : IEqualityComparer<ObjectWithID>
{
public bool Equals(ObjectWithID x, ObjectWithID y)
{
return x.ID == y.ID;
}
public int GetHashCode(ObjectWithID obj)
{
return obj.ID.GetHashCode();
}
}
public interface ObjectWithID {
string ID { get; set; }
}
public class Template : ObjectWithID
{
public string ID { get; set; }
public string Name { get; set; }
public string Age { get; set; }
public string Place { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Country { get; set; }
}
public class Template1 : ObjectWithID
{
public string ID { get; set; }
}
Output:
Matches:
1
3
5
Ummatches:
2
4
6
Press any key to continue . . .
For comparison, this should also work (the first part is a variation on #MAV's answer):
var matches = from item in listForTemplate
join id in listForTemplate1 on item.ID equals id.ID
select item;
var unmatches = listForTemplate.Where(item => matches.All(elem => elem.ID != item.ID));
matches and unmatches will both be IEnumerable<Template> which is the type you require.
However, MAV's answer works fine so I'd go for that one.
As mentioned, Implement the IEqualityComparer<T> interface.
IEqualityComparer<T> MSDN
Then use this as an argument in your method for Except() and Intersect()
Intersect
There is a good example of how to do so on the link for the Intersect() method.
If you don't absolutely have to use LINQ, why not code something like this?
var matches = new List<Template>();
var unmatches = new List<Template>();
foreach (var entry in listForTemplate)
{
bool matched = false;
foreach (var t1Entry in listForTemplate1)
{
if (entry.ID == t1Entry.ID)
{
matches.Add(entry);
matched = true;
break;
}
}
if (!matched)
{
unmatches.Add(entry);
}
}
A disadvantage of the LINQ approach is that you're traversing the lists twice.

How to extract result of Linq Expression?

My result Expression is
var result = dtFields.AsEnumerable().Join(dtCDGroup.AsEnumerable(),
fieldList=>fieldList.Field<string>("CDGroupID"),
cd=>cd.Field<string>("CDGroupID"),
(fieldList,cd) => new
{
FieldID = fieldList.Field<string>("FieldID"),
Name = cd.Field<string>("Name"),
CDCaption = fieldList.Field<string>("CDCaption"),
Priority = ((cd.Field<string>("Priority") == null) ? 99 : cd.Field<int>("Priority")),
fldIndex = fieldList.Field<string>("fldIndex")
}).OrderBy(result => result.Priority).ThenBy(result => result.fldIndex);
Casting above result to array or list throws an invalid cast exception.
How can extract result of above expression?
Add .ToArray() or .ToList() call respectively
Try to add a strongly typed type:
public class NewModule
{
public int FieldID { get; set; }
public string Name { get; set; }
public string CDCaption { get; set; }
public int Priority { get; set; }
public int fldIndex { get; set; }
}
instead of the anonymous type then you could use ToList<NewModule>() like this:
var result = dtFields.AsEnumerable().Join(dtCDGroup.AsEnumerable(),
fieldList=>fieldList.Field<string>("CDGroupID"),
cd=>cd.Field<string>("CDGroupID"),
(fieldList,cd) => new NewModule
{
FieldID = fieldList.Field<string>("FieldID"),
Name = cd.Field<string>("Name"),
CDCaption = fieldList.Field<string>("CDCaption"),
Priority = ((cd.Field<string>("Priority") == null) ? 99 : cd.Field<int>("Priority")),
fldIndex = fieldList.Field<string>("fldIndex")
}).OrderBy(result => result.Priority)
.ThenBy(result => result.fldIndex)
.ToList<NewModule>();

Categories

Resources