I have a linq query as follow:
public static ViewUserDisplayPreferences GetUserDisplayPreferences(int TheUserID)
{
using ( MyDataContext TheDC = new MyDataContext() )
{
var OutputUserDisplayPreferences = from user in TheDC.Users
where user.UserID == TheUserID
select new ViewUserDisplayPreferences
{
UserTimeFormat = user.UserTimeDisplay
};
return (ViewUserDisplayPreferences)(OutputUserDisplayPreferences);
}
}
For the moment, the object ViewUserDisplayPreferences is defined as follow (more variables will be added later):
public class ViewUserDisplayPreferences
{
public string UserTimeFormat { get; set; }
};
On the return statement at runtime, I get this error:
Unable to cast object of type
'System.Data.Linq.DataQuery`1[ObjectsUsers.ViewUserDisplayPreferences]'
to type
'ObjectsUsers.ViewUserDisplayPreferences'.]
What's wrong with the code? The intellisense is not showing any error on the line?
Thanks
OutputUserDisplayPreferences is an IEnumerable<T>. If you want an object, use either the First (if there can be more than one) or Single (if you know for sure only one object will be in the sequence) method on the sequence. If it is possible for the sequence to be empty, use the respective *OrDefault method.
Linq returns a collection. Try adding a .FirstOrDefault to the end.
Related
Could someone suggest a way for me to select one of the lists within a parent list where one of it's elements has a certain property value?
public class HierarchyLevel
{
public string Abbreviation;
public string Name;
public string Value;
public Type LevelType;
public List<HierarchyLevel> Children = new List<HierarchyLevel>();
}
public static List<List<HierarchyLevel>> ElementaryTypes = new List<List<HierarchyLevel>>();
I am actually trying to get the List that has the LevelType field of a specific type.
You wrote:
I am actually trying to get the List that has the LevelType field of a specific type.
What do you want if you've got several HierarchyLevels with this LevelType? And what do you want if there are no HierarchyLevels at all with this LevelType?
Let's assume that you want all HierarchyLevels with this LevelType. If later on you only want the first, or the one with a certain Abbreviation (or whatever), you could always use .FirstOrDefault, or .Where. and do a ToList in the end.
Implementing it as an extension function. See Extension Methods Demystified
public static IEnumerable<HierarchyLevel> GetHierarchyLevelsWithLevelType(
this IEnumerable<HierarchyLevel> hierarchyLevels,
LevelType desiredLevelType)
{
foreach (var hierarchyLevel in hierarchyLevels)
{
if (hierarchyLevel.LevelType == desiredLevelType)
{ // found one!
yield return hierarchyLevel;
}
// using recursion: check all the Children
IEnumerable<HierarchyLevel> childrenWithDesiredLevelType = hierarchyLevel.Children
.GetHierarchyLevelsWithLevelType(desiredLevelType);
foreach(var childWithDesiredLevelType in childrenWithDesiredLevelType)
{
yield return childWithDesiredLevelType;
}
}
}
Because of the recursion all Grandchildren and their Children etc will be returned
usage:
var allSpecialHierarchies = myHierarchies.GetHierarchyLevelsWithLevelType(LevelType.Special);
// get the first:
var firstSpecialHierarchy = allSpecialHierarchies.FirstOrDefault();
// get the first three named "Shakespeare:
var threeShakesPeares = allSpecialHierarchies
.Where(hierarchyLevel => hierarchyLevel.Name == "Shakespeare")
.Take(3)
For better usage you should provide a version that has a parameter IQualityComparer<LevelType>. Let the function above call that one.
And a nice challenge: to be fully LINQ compatible, create a version with a predicate that returns a type T and an equality comparer for this type T, so that you can have all HierarchyLevels with a certain Name, or Abbreviation.
You can Solve your with the help of recursion consider example below :- I have taken sample type of String you can use any of your Type
List<List<HierarchyLevel>> sample = new List<List<HierarchyLevel>>();
Type yourType = typeOf(string);
List<HierarchyLevel> filtered = sample.Where(x => ContainsElement(x, yourType));
public void bool ContainsElement(List<HierarchyLevel> list,Type yourType)
{
if(list.Any(x => x.LevelType == yourType) //check if current node has same level type
return true;
else if(list.Childern.Count > 0) //check if current node has children if yes then call ContainsElement again
return list.Children.Any(x => ContainsElement(x,yourType));
else
return false; //else return false in last
}
Thanks to user743414 for pointing out how simple this was :)
By using a dictionary instead, I could reference to the specific list. (This is also a faster option.)
Dictionary<Type,List<HierarchyLevel>> HierarchicalData;
I can now use it with a key of 'Type':
private void UpdateGeneralData(object Entity, Dictionary<Type,List<HierarchyLevel>> TypeData)
{
CBType.Items.Clear();
foreach (var item in TypeData[Entity.GetType()])
{
CBType.Items.Add(item);
}
}
Something like this (?):
List<HierarchyLevel> var = hLevel.Select(h => h.Children.Where(c => c.Param = "desired param")).ToList();
my code supposed to check two conditions and return the values but when i try to return q this error shows up
Cannot implicitly convert type 'System.Collections.Generic.List<< anonymous type: string Name, string File>>' to 'System.Collections.Generic.List< string>
and i tried everything but nothing worked also don't know to set List<string> or set it as List<EF_Model.PDF> ,PDF is a DTO in my model
this is my code
internal List<string> Customers_File(int _id)
{
using (var Context = new EF_Model.CoolerEntities())
{
var q = from c in Context.Customers
where c.Id == _id &&
c.Ref_PDF != null
select new { c.PDF.Name, c.PDF.File };
return q.ToList();
}
}
You have to convert the anonymous object into a string representation.(Note I'm using C# 6.0 feature - string interpolation, you can replace it with string.Format in the previous versions.
Example:
return q.Select(x=>$"Name = {x.PDF.Name} File = {c.PDF.File}").ToList();
You have declared your return type as string but are returning an a list of anonymous objects with two properties. That won't work. If you want to return a string you need to create a single string per list item. If you want to return object change your return type
You are getting this error because you have defined Customers_File as returning a list of strings. However, the list q that you return doesn't fit that description.
In your query, when you do
select new { c.PDF.Name, c.PDF.File };
..you are making an Anonymous Type, and storing it in the collection q. This type has two fields and is clearly not a string.
Some possible solutions are:
Change your method to have return type List<object> instead of List<string> (not recommended).
Make your object into a string via some form of serialization (JSON or XML).
Create a class or struct for this data and change the return type of your method to List<dataClass>
You need to define an object with your to properties
public class PdfInfo
{
public string Name{get;set;}
public string File{get;set;}
}
Return a list of them from your method
internal List<PdfInfo> Customers_File(int _id)
And finally project to those, in place of an anonymous object:
....
select new PdfInfo() { Name=c.PDF.Name, File = c.PDF.File };
Question I'm trying something new here with a program I made earlier. In the first program I was able to drag and drop table adapters and use the generic "var" to store query results. Now I'm trying to create a new program that has some separation of code. For example in the first program I had all of the code written in the form.cs file, this time I'd like to create a class to run the queries and return them to the calling class, however, how do you store a query result that contains many types? You cant return a var variable, it must be more specific. I get an error on the select line that reads: "Cannot implicitly convert type'System.Collections.Generic.IEnumerable' to 'System.Collections.Generic.IEnumerable;. An explicit conversion exists(are you missing a cast?)
Can some one help me? What is the cast? The first method (public IEnumerable getList()) works as expected its the second method, (public IEnumerable getRecipeInfo(string recipeName)) where I get the error. Here's my code so far.
namespace recipeDataBase
{
class Query
{
recipiesNewDataSet recipeDataSet = new recipiesNewDataSet();
recipiesNewDataSetTableAdapters.RecipeTableAdapter recipeTableAdapter = new recipiesNewDataSetTableAdapters.RecipeTableAdapter();
recipiesNewDataSetTableAdapters.RecipeIngredientTableAdapter ingredientTableAdapter = new recipiesNewDataSetTableAdapters.RecipeIngredientTableAdapter();
recipiesNewDataSetTableAdapters.RatingTableAdapter ratingTableAdapter = new recipiesNewDataSetTableAdapters.RatingTableAdapter();
public Query()
{
}
public IEnumerable<string> getList()
{
recipeTableAdapter.Fill(recipeDataSet.Recipe);
IEnumerable<string> recipeList = (from a in recipeDataSet.Recipe
select a.RecipeName);
return recipeList;
}
public IEnumerable<string> getRecipeInfo(string recipeName)
{
recipeTableAdapter.Fill(recipeDataSet.Recipe);
ratingTableAdapter.Fill(recipeDataSet.Rating);
ingredientTableAdapter.Fill(recipeDataSet.RecipeIngredient);
IEnumerable<string> recipeInfo = (from a in recipeDataSet.Recipe
from b in recipeDataSet.Rating
from c in recipeDataSet.RecipeIngredient
where a.RecipeName == recipeName &&
a.RecipeNum == c.RecipeNum &&
a.RatingNum == b.RatingNum
select new { a.RecipeName, a.Nationality, a.Event, a.Source, b.FamilyRating, c.Ingredient });
return recipeInfo;
}
}
}
Thanks in advance for any help!!
You're getting an exception because you select an anonymous type in your query but the type of the query variable is IEnumerable<string>. Instead you must either select a string, use the var keyword or a custom class instead.
If you want to return something useful, i would create a custom class with all of these properties you have selected in the anonymous type, for example:
public class Recipe
{
public String RecipeName{ get; set;}
public String Nationality{ get; set;}
public String Event{ get; set;}
// ...
}
Then you can return an IEnumerable<Recipe> instead from the method and select instances in the query:
...
select new Recipe(){ RecipeName=a.RecipeName, Nationality=a.Nationality, Event=a.Event,... });
Side-note: I would suggest to use Join instead of Where in the query:
Why is LINQ JOIN so much faster than linking with WHERE?
You are using an anonymous type so this:
var recipeInfo = (from a in recipeDataSet.Recipe
from b in recipeDataSet.Rating
from c in recipeDataSet.RecipeIngredient
where a.RecipeName == recipeName &&
a.RecipeNum == c.RecipeNum &&
a.RatingNum == b.RatingNum
select new { a.RecipeName, a.Nationality, a.Event, a.Source, b.FamilyRating, c.Ingredient }).ToList();
...Gives you an IEnumerable of an anonymous type with 6 values, possibly all strings. var doesn't stand for "variant" and is still a strongly-typed declaration, only it is resolved at compile-time (which will fail if the type can't be inferred from usage). Thus, the above code makes var mean IEnumerable<anonymous_type_with_6_strings> at compile-time, but the return statement attempts to make this IEnumerable<string> - this is where you're getting the compile-time cast exception.
I suggest you create a simple class to hold RecipeInfo values and so your method could return IEnumerable<RecipeInfo>:
class RecipeInfo
{
public string RecipeName {get;set;}
public string Nationality {get;set;}
public string Event {get;set;}
public string Source {get;set;}
public string FamilyRating {get;set;}
public string Ingredient {get;set;}
}
And then you can project your selection into this type:
var recipeInfo = (from a in recipeDataSet.Recipe
from b in recipeDataSet.Rating
from c in recipeDataSet.RecipeIngredient
where a.RecipeName == recipeName &&
a.RecipeNum == c.RecipeNum &&
a.RatingNum == b.RatingNum
select new RecipeInfo{RecipeName=a.RecipeName, Nationality=a.Nationality, Event=a.Event, Source=a.Source, FamilyRating=b.FamilyRating, Ingredient=c.Ingredient }).ToList();
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Accessing C# Anonymous Type Objects
Working with C# Anonymous Types
I'm using linq to entities to get id and full name from a table with customers.
public IQueryable RegresaClientesPorEmpresa(int id_emp)
{
var clientes = from c in context.clientes
where c.IDEmpresa == id_emp
select new
{
c.IDCliente,
NomComp = c.Nombres +" "+ c.ApellidoP +" "+ c.ApellidoM
};
return clientes;
}
The result is used as the datasource of a combobox, then when SelectionChangeCommitted is triggered in my combo, I want the selected item to be added to a listbox:
var clientes = operaciones.RegresaClientesPorEmpresa(2);
combo_cliente.DataSource = clientes;
combo_cliente.DisplayMember = "NomComp";
combo_cliente.ValueMember = "IDCliente";
listBox_grupo.DisplayMember = "NomComp";
listBox_grupo.ValueMember = "IDCliente";
private void combo_cliente_SelectionChangeCommitted(object sender, EventArgs e)
{
listBox_grupo.Items.Add(combo_cliente.SelectedItem);
}
Until here everything is fine. Finally I want to get all "IDCliente"'s values from all items added to my listbox, the problem is that I don't know how to do it because every item is an Anonymous data type. Can anyone help me?
The scope of an anonymous type is limited to the method in which it is "declared" (well it's not really declared, but you see what I mean). If you want to use the result of your query in another method, create a named type to hold the results.
You shouldn't return anonymous types from your methods if you're expecting to access their properties. It'll be easier on you if you define a class instead, because that establishes the contract of your method.
just create a class to avoid anonymous type.
class Foo
{
public string NomComp {get ; set;}
public string IDCliente {get ; set;}
}
and do
select new Foo
{
...
}
to save some hassle.
or You can define
T Cast<T>(object obj, T type)
{
return (T)obj;
}
and then use
object anonymousObject = GetSelection();
var selection = Cast(anonymousObject , new { IDCliente="", NomComp ="" });
and then you should be able to do selection.NomComp to get the property value.
This is my function:
private IEnumerable<string> SeachItem(int[] ItemIds)
{
using (var reader = File.OpenText(Application.StartupPath + #"\temp\A_A.tmp"))
{
var myLine = from line in ReadLines(reader)
where line.Length > 1
let id = int.Parse(line.Split('\t')[1])
where ItemIds.Contains(id)
let m = Regex.Match(line, #"^\d+\t(\d+)\t.+?\t(item\\[^\t]+\.ddj)")
where m.Success == true
select new { Text = line, ItemId = id, Path = m.Groups[2].Value };
return myLine;
}
}
I get a compile error,because "myLine" is not a IEnumerable[string] and I don't know how to write IEnumerable[Anonymous]
"Cannot implicitly convert type 'System.Collections.Generic.IEnumerable[AnonymousType#1]' to 'System.Collections.Generic.IEnumerable[string]'"
You cannot declare IEnumerable<AnonymousType> because the type has no (known) name at build time. So if you want to use this type in a function declaration, make it a normal type. Or just modify your query to return a IENumerable<String> and stick with that type.
Or return IEnumerable<KeyValuePair<Int32, String>> using the following select statement.
select new KeyValuePair<Int32, String>(id, m.Groups[2].Value)
I am not necessarily recommending this...
It is a kind of subversion of the type system but you could do this:
1) change your method signature to return IEnumerable (the non generic one)
2) add a cast by example helper:
public static class Extensions{
public static IEnumerable<T> CastByExample<T>(
this IEnumerable sequence,
T example) where T: class
{
foreach (Object o in sequence)
yield return o as T;
}
}
3) then call the method something like this:
var example = new { Text = "", ItemId = 0, Path = "" };
foreach (var x in SeachItem(ids).CastByExample(example))
{
// now you can access the properties of x
Console.WriteLine("{0},{1},{2}", x.Text, x.ItemId, x.Path);
}
And you are done.
The key to this is the fact that if you create an anonymous type with the same order, types and property names in two places the types will be reused. Knowing this you can use generics to avoid reflection.
Hope this helps
Alex
The method signature on SearchItem indicates that the method returns an IEnumerable<string> but the anonymous type declared in your LINQ query is not of type string. If you want to keep the same method signature, you have to change your query to only select strings. e.g.
return myLine.Select(a => a.Text);
If you insist on returning the data selected by your query, you can return an IEnumerable<object> if you replace your return statement with
return myLine.Cast<object>();
Then you can consume the objects using reflection.
But really, if your going to be consuming an anonymous type outside the method that it is declared in, you should define a class an have the method return an IEnumerable of that class. Anonymous types are convenience but they are subject to abuse.
Your function is trying to return IEnumerable<string>, when the LINQ statement you are executing is actually returning an IEnumerable<T> where T is a compile-time generated type. Anonymous types are not always anonymous, as they take on a specific, concrete type after the code is compiled.
Anonymous types, however, since they are ephemeral until compiled, can only be used within the scope they are created in. To support your needs in the example you provided, I would say the simplest solution is to create a simple entity that stores the results of your query:
public class SearchItemResult
{
public string Text { get; set; }
public int ItemId { get; set; }
public string Path { get; set; }
}
public IEnumerable<SearchItemResult> SearchItem(int[] itemIds)
{
// ...
IEnumerable<SearchItemResult> results = from ... select new SearchItemResult { ... }
}
However, if your ultimate goal is not to retrieve some kind of object, and you are only interested in, say, the Path...then you can still generate an IEnumerable<string>:
IEnumerable<string> lines = from ... select m.Groups[2].Value;
I hope that helps clarify your understanding of LINQ, enumerables, and anonymous types. :)
Return a ValueTuple instead of an anonymous class. Ex (using "named tuples")-
(Text: line, ItemId: id, Path: m.Groups[2].Value)
https://learn.microsoft.com/en-us/dotnet/csharp/tuples
Instead of-
new { Text = line, ItemId = id, Path = m.Groups[2].Value }
The ValueTuple is part of C# version 7 and was originally implemented as a separate NuGet package (System.ValueTuple). Starting with .NET 4.7 it is a built-in type. For .NET Core, versions prior to 2.0 required the NuGet package but it is built-in with version 2.0.
The question was asked a long time ago, I hope it helps someone...
"You cannot declare IEnumerable", instead, must convert it to a "custom" IEnumerable:
public class MyString
{
public string String { get; set; } = string.Empty;
}
public IEnumerable<MyString> GetMyStrings(List<string> Strings)
{
var AnonString = from S in Strings group S by S into Grouped select new { String = Grouped.Key };
IEnumerable<MyString> Result = AnonString.Select(x => new MyString() { String = x.String }).ToArray();
return Result;
}
Regards.
this link could be useful for others who end up here
https://idreesdotnet.blogspot.com/2019/08/c-how-to-create-list-of-anonymous-type.html
the first solution (of 6) is delightlfully simple
1: First create the object(s) of anonymous type and then pass it to an array and call ToList() method.
var o1 = new { Id = 1, Name = "Foo" };
var o2 = new { Id = 2, Name = "Bar" };
var list = new[] { o1, o2 }.ToList();