I have an IEnumerable list with multi value in it, and I want to foreach over its values. I have this code
IEnumerable<object> Place = db.Places.Select(x => new { Id = x.Id, Nam1 = x.Name1, Name2 = x.Name2);
foreach(dynamic thisPlace in Place)
{
Response.Write (thisPlace.Id)
Response.Write (thisPlace.Name1)
Response.Write (thisPlace.Name2)
}
This code work fine and after it's done, it throws an error:
A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.Place_F6C785C74658C47ED4BFCF45D13FE7D754CCA2F688B6CBDD079244CE52B46291'."
Now the question is how to do foreach with IEnumerable the right way?
First of all, your code wont get executed. Because you do not have property named Name1 as you showed in the code.
Second, even if you have you should use var instead of using IEnumerable<object>
var Places = db.Places.Select(x => new { Id = x.Id, Nam1 = x.Name1, Name2 = x.Name2}).ToList();
foreach (var thisPlace in Places)
{
Response.Write(thisPlace.Id)
Response.Write(thisPlace.Name1)
Response.Write(thisPlace.Name2)
}
Related
I have the following helper function that uses reflection to look at the supplied model, check if any fields are non-null, and overwrite those with new values in MongoDB.
It works fine until I try updating a List<string> field. Instead of saving the list as an array to MongoDB, it saves a string value of "(Collection)" in MongoDB. What am I missing to make this work?
I don't want to hardcode that any List should default to List<string> either. It's possible I could have lists of ints.
public override MyObj Update(MyObj model)
{
var builder = Builders<MyObj>.Update;
var builder_def = builder.Set(x => x.Id, model.Id);
foreach (PropertyInfo prop in model.GetType().GetProperties())
{
var value = model.GetType().GetProperty(prop.Name).GetValue(model, null);
if (value != null)
{
builder_def = builder_def.Set(prop.Name, value); // Not setting lists correctly
}
}
var filter = Builders<MyObj>.Filter;
var filter_def = filter.Eq(x => x.Id, model.Id);
Connection.Update(filter_def, builder_def);
return model;
}
Edit
I think my problem is related to this open bug https://jira.mongodb.org/browse/CSHARP-1984. Given that, is there any way for me to make this work in that context?
I need your help
I just wrote the following code
var anynomousObject = new { Amount = 10, weight = 20 };
List<object> ListOfAnynomous = new List<object> { anynomousObject };
var productQuery =
from prod in ListOfAnynomous
select new { prod.Amount, prod.weight }; // here it object on 'prod.Amount, prod.weight' that the object defenetion does not contains the "Amount" and "weight" properties
foreach (var v in productQuery)
{
Console.WriteLine(v.Amount, v.weight);
}
so please could you help me to solve this problem.
You need to make a class of your object definition, or using the dynamic keywork instead of boxing in object :
var anynomousObject = new { Amount = 10, weight = 20 };
List<dynamic> ListOfAnynomous = new List<dynamic> { anynomousObject };
var productQuery =
from prod in ListOfAnynomous
select new { prod.Amount, prod.weight };
foreach (var v in productQuery)
{
Console.WriteLine(v.Amount, v.weight);
}
this is because, when you box as object, the compiler doesn't know the definition of your anonymous var. Dynamic make it evaluate at runtime instead of compile-time.
The other option is to create a class or struct.
Your List<object> has a list of objects. The Linq query looks this list, and all it sees are regular objects.
Either use a class or a structure to store your objects, or use List<dynamic>
I'm new to using Dynamic Objects in C#. I am reading a CSV file very similarly to the code found here: http://my.safaribooksonline.com/book/programming/csharp/9780321637208/csharp-4dot0-features/ch08lev1sec3
I can reference the data I need with a static name, however I can not find the correct syntax to reference using a dynamic name at run time.
For example I have:
var records = from r in myDynamicClass.Records select r;
foreach(dynamic rec in records)
{
Console.WriteLine(rec.SomeColumn);
}
And this works fine if you know the "SomeColumn" name. I would prefer to have a column name a a string and be able to make the same type refrence at run time.
Since one has to create the class which inherits from DynamicObject, simply add an indexer to the class to achieve one's result via strings.
The following example uses the same properties found in the book example, the properties which holds the individual line data that has the column names. Below is the indexer on that class to achieve the result:
public class myDynamicClassDataLine : System.Dynamic.DynamicObject
{
string[] _lineContent; // Actual line data
List<string> _headers; // Associated headers (properties)
public string this[string indexer]
{
get
{
string result = string.Empty;
int index = _headers.IndexOf(indexer);
if (index >= 0 && index < _lineContent.Length)
result = _lineContent[index];
return result;
}
}
}
Then access the data such as
var csv =
#",,SomeColumn,,,
ab,cd,ef,,,"; // Ef is the "SomeColumn"
var data = new myDynamicClass(csv); // This holds multiple myDynamicClassDataLine items
Console.WriteLine (data.OfType<dynamic>().First()["SomeColumn"]); // "ef" is the output.
You will need to use reflection. To get the names you would use:
List<string> columnNames = new List<string>(records.GetType().GetProperties().Select(i => i.Name));
You can then loop through your results and output the values for each column like so:
foreach(dynamic rec in records)
{
foreach (string prop in columnNames)
Console.Write(rec.GetType().GetProperty (prop).GetValue (rec, null));
}
Try this
string column = "SomeColumn";
var result = rec.GetType().GetProperty (column).GetValue (rec, null);
I think I understand returning records of an anonymous type from But in this I want to create NEW CatalogEntries, and set them from the values selected. (context is a Devart LinqConnect database context, which lets me grab a view).
My solution works, but it seems clumsy. I want to do this in one from statement.
var query = from it in context.Viewbostons
select it;
foreach (GPLContext.Viewboston item in query)
{
CatalogEntry card = new CatalogEntry();
card.idx = item.Idx;
card.product = item.Product;
card.size = (long)item.SizeBytes;
card.date = item.Date.ToString();
card.type = item.Type;
card.classification = item.Classification;
card.distributor = item.Distributor;
card.egplDate = item.EgplDate.ToString();
card.classificationVal = (int)item.ClassificationInt;
card.handling = item.Handling;
card.creator = item.Creator;
card.datum = item.Datum;
card.elevation = (int)item.ElevationFt;
card.description = item.Description;
card.dirLocation = item.DoLocation;
card.bbox = item.Bbox;
card.uniqID = item.UniqId;
values.Add(card);
}
CatalogResults response = new CatalogResults();
I just tried this:
var query2 = from item in context.Viewbostons
select new CatalogResults
{ item.Idx,
item.Product,
(long)item.SizeBytes,
item.Date.ToString(),
item.Type,
item.Classification,
item.Distributor,
item.EgplDate.ToString(),
(int)item.ClassificationInt,
item.Handling,
item.Creator,
item.Datum,
(int)item.ElevationFt,
item.Description,
item.DoLocation,
item.Bbox,
item.UniqId
};
But I get the following error:
Error 79 Cannot initialize type 'CatalogService.CatalogResults' with a
collection initializer because it does not implement
'System.Collections.IEnumerable' C:\Users\ysg4206\Documents\Visual
Studio
2010\Projects\CatalogService\CatalogService\CatalogService.svc.cs 91 25 CatalogService
I should tell you what the definition of the CatalogResults is that I want to return:
[DataContract]
public class CatalogResults
{
CatalogEntry[] _results;
[DataMember]
public CatalogEntry[] results
{
get { return _results; }
set { _results = value; }
}
}
My mind is dull today, apologies to all. You are being helpful. The end result is going to be serialized by WCF to a JSON structure, I need the array wrapped in a object with some information about size, etc.
Since .NET 3.0 you can use object initializer like shown below:
var catalogResults = new CatalogResults
{
results = context.Viewbostons
.Select(it => new CatalogEntry
{
idx = it.Idx,
product = it.Product,
...
})
.ToArray()
};
So if this is only one place where you are using CatalogEntry property setters - make all properties read-only so CatalogEntry will be immutable.
MSDN, Object initializer:
Object initializers let you assign values to any accessible fields or properties of an
object at creation time without having to explicitly invoke a constructor.
The trick here is to create a IQueryable, and then take the FirstOrDefault() value as your response (if you want a single response) or ToArray() (if you want an array). The error you are getting (Error 79 Cannot initialize type 'CatalogService.CatalogResults' with a collection initializer because it does not implement 'System.Collections.IEnumerable') is because you're trying to create an IEnumerable within the CatalogEntry object (by referencing the item variable).
var response = (from item in context.Viewbostons
select new CatalogEntry()
{
idx = item.Idx,
product = item.Product,
size = (long)item.SizeBytes,
...
}).ToArray();
You don't have to create anonymous types in a Linq select. You can specify your real type.
var query = context.Viewbostons.Select( it =>
new CatalogEntry
{
idx = it.idx,
... etc
});
This should work:
var query = from it in context.Viewbostons
select new CatalogEntry()
{
// ...
};
In this slice of code i'm adding ColumnInfo's to a list,
In my view the getter expression passed to the ColumnInfo get's called upon my rows.
This all works fine except for the local variable "childt.Naam" that get's used in my lambda expression.
The runtime evaluation causes childt.Naam to always be the one of the last childt passed in the foreach.
How can I make sure these "local variables" get passed correctly to the expression
foreach (var childt in itemt.ItemTemplates)
{
columns.Add(new ColumnInfo<Item>(model => level(model).GetV(childt.Naam, model.Taal) + childt.Naam, childt.Naam, new TextPropertyRenderer(), editable));
}
Here's the relevant parts of constructor of the ColumnInfo class
public ColumnInfo(Expression<Func<TModel, object>> getter, string title, IPropertyRenderer renderer, bool editable = false)
{
this.renderer = renderer;
this.Editable = editable;
this.Getter = getter.Compile();
}
It is because of the deferred aspect of LINQ so you need to create separate space for values.
foreach (var childt in itemt.ItemTemplates)
{
var naam = childt.Naam;
columns.Add(new ColumnInfo<Item>(model =>
level(model).GetV(naam, model.Taal) + naam,
naam,
new TextPropertyRenderer(),
editable));
}
http://msdn.microsoft.com/en-us/library/bb882641.aspx
You are closing over the loop variable - just make local copy:
foreach (var childt in itemt.ItemTemplates)
{
var localChildt = childt;
columns.Add(new ColumnInfo<Item>(model => level(model).GetV(localChildt.Naam, model.Taal) + localChildt.Naam, localChildt.Naam, new TextPropertyRenderer(), editable));
}
Also see "Closing over the loop variable considered harmful"
This issue is known as 'access to modified closure'.
To fix it, create a local variable in the loop body, assign childt to it, and use it in the lambda expressions:
foreach (var childt in itemt.ItemTemplates)
{
var c = childt;
columns.Add(new ColumnInfo<Item>(model => level(model).GetV(c.Naam, model.Taal) + c, c.Naam, new TextPropertyRenderer(), editable));
}