Problem in LINQ query formation - c#-3.0

I have written
List<int> Uids = new List<int>();
Uids = (from returnResultSet in ds.ToList()
from portfolioReturn in returnResultSet.Portfolios
from baseRecord in portfolioReturn.ChildData
select new int
{
id = baseRecord.Id
}).ToList<int>();
Getting error: 'int' does not contain a definition for 'id'
what is the problem that i created?
Thanks

Try this:
List<int> Uids = (from returnResultSet in ds.ToList()
from portfolioReturn in returnResultSet.Portfolios
from baseRecord in portfolioReturn.ChildData
select baseRecord.Id).ToList<int>();
Since you want to get a list of integers you can simply project the Id property from your query and then use the ToList extension method to buffer them into a List<T>. As a side note, are you certain that a List<T> is the right type to use here? You are forgoing the benefit of deferred execution and will not be able to stream these ids if you buffer them into a List<T>.

Your code is trying to instantiate ints, setting an id property that doesn't exist. I think the following is what you need.
Uids = (from returnResultSet in ds.ToList()
from portfolioReturn in returnResultSet.Portfolios
from baseRecord in portfolioReturn.ChildData
select baseRecord.Id).ToList<int>();

The problem is with the: select new int {} part.
Try simply doing:
List<int> Uids = new List<int>();
Uids = (from returnResultSet in ds.ToList()
from portfolioReturn in returnResultSet.Portfolios
from baseRecord in portfolioReturn.ChildData
select baseRecord.Id
)
.ToList<int>();
select new {} syntax is for defining anonymous types (where use is limited to the same function scope).
Andrew.

Related

How to change the value of a tables attribute using LINQ/LAMBDA?

I have an order table and an orderStatus table, their relationship is as seen below:
I want to be able to change 'StatusID' to the value 2, of a specific order (i am able to get the specific order ID, and have loaded it into an integer variable) using a lambda expression within an action result - would there be any easy way of doing this?
So far i have tried:
//get specific order ID
int currentOrderId = newConfirmedOrderLine.OrderID;
//-----
Order statusChange = new Order();
statusChange.OrderStatus.StatusID = 2;
DBAccessor.SaveChanges();
I am new to linq and lambda, so any explanation with an answer would be greatly appreciated!
If DBAccessor is a DbContext then this could/should work. You need to load the Order entity that you want to change from the DBAccessor.Order DbSet, change it by setting a property, and then call SaveChanges.
var orderStatus = DBAccessor.OrderStatus.First(x => x.StatusID == 2);
var order = DBAccessor.Order.Find(currentOrderId);
order.OrderStatus = orderStatus;
DBAccessor.SaveChanges();

In C#, how do I get a distinct value from an IEnumerable using LINQ?

I have an IEnumerable variable that I want to extract a distinct value from. I know all the entries in the rows of the list have the same value, I just need to get that value.
The method returns an IEnumerable.
The row in the IEnumerable is defined as:
QuoteCovId
AdditionalInterestId
AdditionalInterestsAffiliateId
AdditionalInterestsLastName
AdditionalInterestsBusinessAddrLine1
AdditionalInterestsBusinessCity
AdditionalInterestsBusinessState
AdditionalInterestsBusinessZip
Sampel of code:
IadditionalInterestData = AdditionalInterestData.GetAdditionalInterests(MasterPkgID, Requestor);
// Using linq.
var quotes = from ai in IadditionalInterestData
select Distinct(ai.QuoteCovId);
// Iterate thru to get the 1 value.
foreach (int QuoteCovId in quotes)
{
quoteID = QuoteCovId;
}
var quoteId = AdditionalInterestData.GetAdditionalInterests(MasterPkgID, Requestor)
.FirstOrDefault().Select(f => f.QuoteCovId);
But that method:
AdditionalInterestData.GetAdditionalInterests(MasterPkgID, Requestor);
returns me an IEnumerable which I will use further in my application. Which is what I need.
So how will your suggestion still give me that IEnumerable and give me the quote value which happens to be the same in the collection?
var quoteId = AdditionalInterestData.GetAdditionalInterests(MasterPkgID, Requestor).FirstOrDefault().Select(f => f.QuoteCovId);
Also, I just added your line of code as is and I get an error statement.

MongoDB C# - update using custom strongly-typed objects not allowed?

I am trying to perform an update using strongly-typed objects. For example,
public void setAppointmentPrefs(string UserName, IEnumerable<AppointmentInfo> info)
{
var query = new QueryDocument {{ "ProviderId", UserName}};
var update = Update.Set("Prefs",prefs); // prefs.toList() gives same error
// providerprefs initialized in constructor
providerprefs.Update(query, update);
}
I receive a compiler error saying:Error 14 The best overloaded method match for 'MongoDB.Driver.Builders.Update.Set(string, MongoDB.Bson.BsonValue)' has some invalid arguments
Obviously the Mongo driver will not let me update based on my own object (whether as IEnumerable or prefs.toList()), which seems a contrast from the way it permits me to insert or query with custom objects. Surely I am missing something obvious that would permit me to avoid deserializing, weakly typing then creating a generic BsonDocument!! TIA.
You can do an Update based on your own types! Have you tried using the typed Query and Update builders?
Try something like this:
var query = Query<AppointmentInfo>.EQ(i => i.ProviderId, userName);
var update = Update<AppointmentInfo>.Set(i => i.Prefs, info.Prefs);
Not sure I got the types and everything write from your partial code, but that should give you the general idea.
Let me know if you have any further questions.
I know this has been answered but I for one don't fully understand Roberts answer.
All I did is call the "ToBsonDocument()" method for it to except the object as a parameter
So:
customObject.ToBsonDocument()
If you have an array of objects inside a document:
var query = Query.EQ("_id", ObjectId.Parse(id.ToString()));
var update = Update.Push("ArrayOfObjects", customObject.ToBsonDocument());
collection.Update(query, update);

How do we convert a column from table to an arraylist using ormlite?

I'm trying to convert an entire column values into a arrayList using ormlite on android, is this possible, with direct api?
Using raw results i get close, but not quite:
GenericRawResults<String[]> rawResults =
getHelper().getMyProcessDao().queryRaw(
queryBuild.selectColumns("nid").prepareStatementString());
List<String[]> result = rawResults.getResults();
Hrm. I'm not sure this is what you want. However, one way to accomplish what you ask for specifically is through by using the RawRowMapper which can be passed to ORMLite's DAO method: dao.queryRaw(String, Rowmapper, String...).
Something like the following should work:
RawRowMapper<Integer> mapper = new RawRowMapper<Integer>() {
public Integer mapRow(String[] columnNames, String[] resultColumns) {
// maybe you should verify that there _is_ only 1 column here
// maybe you should handle the possibility of a bad number and throw
return Integer.parseInt(resultColumns[0]);
}
};
GenericRawResults<Integer> rawResults =
getHelper().getMyProcessDao().queryRaw(
queryBuild.selectColumns("nid").prepareStatementString(), mapper);
List<Integer> list = rawResults.getResults();

ADO.NET Mapping From SQLDataReader to Domain Object?

I have a very simple mapping function called "BuildEntity" that does the usual boring "left/right" coding required to dump my reader data into my domain object. (shown below) My question is this - If I don't bring back every column in this mapping as is, I get the "System.IndexOutOfRangeException" exception and wanted to know if ado.net had anything to correct this so I don't need to bring back every column with each call into SQL ...
What I'm really looking for is something like "IsValidColumn" so I can keep this 1 mapping function throughout my DataAccess class with all the left/right mappings defined - and have it work even when a sproc doesn't return every column listed ...
Using reader As SqlDataReader = cmd.ExecuteReader()
Dim product As Product
While reader.Read()
product = New Product()
product.ID = Convert.ToInt32(reader("ProductID"))
product.SupplierID = Convert.ToInt32(reader("SupplierID"))
product.CategoryID = Convert.ToInt32(reader("CategoryID"))
product.ProductName = Convert.ToString(reader("ProductName"))
product.QuantityPerUnit = Convert.ToString(reader("QuantityPerUnit"))
product.UnitPrice = Convert.ToDouble(reader("UnitPrice"))
product.UnitsInStock = Convert.ToInt32(reader("UnitsInStock"))
product.UnitsOnOrder = Convert.ToInt32(reader("UnitsOnOrder"))
product.ReorderLevel = Convert.ToInt32(reader("ReorderLevel"))
productList.Add(product)
End While
Also check out this extension method I wrote for use on data commands:
public static void Fill<T>(this IDbCommand cmd,
IList<T> list, Func<IDataReader, T> rowConverter)
{
using (var rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
list.Add(rowConverter(rdr));
}
}
}
You can use it like this:
cmd.Fill(products, r => r.GetProduct());
Where "products" is the IList<Product> you want to populate, and "GetProduct" contains the logic to create a Product instance from a data reader. It won't help with this specific problem of not having all the fields present, but if you're doing a lot of old-fashioned ADO.NET like this it can be quite handy.
Although connection.GetSchema("Tables") does return meta data about the tables in your database, it won't return everything in your sproc if you define any custom columns.
For example, if you throw in some random ad-hoc column like *SELECT ProductName,'Testing' As ProductTestName FROM dbo.Products" you won't see 'ProductTestName' as a column because it's not in the Schema of the Products table. To solve this, and ask for every column available in the returned data, leverage a method on the SqlDataReader object "GetSchemaTable()"
If I add this to the existing code sample you listed in your original question, you will notice just after the reader is declared I add a data table to capture the meta data from the reader itself. Next I loop through this meta data and add each column to another table that I use in the left-right code to check if each column exists.
Updated Source Code
Using reader As SqlDataReader = cmd.ExecuteReader()
Dim table As DataTable = reader.GetSchemaTable()
Dim colNames As New DataTable()
For Each row As DataRow In table.Rows
colNames.Columns.Add(row.ItemArray(0))
Next
Dim product As Product While reader.Read()
product = New Product()
If Not colNames.Columns("ProductID") Is Nothing Then
product.ID = Convert.ToInt32(reader("ProductID"))
End If
product.SupplierID = Convert.ToInt32(reader("SupplierID"))
product.CategoryID = Convert.ToInt32(reader("CategoryID"))
product.ProductName = Convert.ToString(reader("ProductName"))
product.QuantityPerUnit = Convert.ToString(reader("QuantityPerUnit"))
product.UnitPrice = Convert.ToDouble(reader("UnitPrice"))
product.UnitsInStock = Convert.ToInt32(reader("UnitsInStock"))
product.UnitsOnOrder = Convert.ToInt32(reader("UnitsOnOrder"))
product.ReorderLevel = Convert.ToInt32(reader("ReorderLevel"))
productList.Add(product)
End While
This is a hack to be honest, as you should return every column to hydrate your object correctly. But I thought to include this reader method as it would actually grab all the columns, even if they are not defined in your table schema.
This approach to mapping your relational data into your domain model might cause some issues when you get into a lazy loading scenario.
Why not just have each sproc return complete column set, using null, -1, or acceptable values where you don't have the data. Avoids having to catch IndexOutOfRangeException or re-writing everything in LinqToSql.
Use the GetSchemaTable() method to retrieve the metadata of the DataReader. The DataTable that is returned can be used to check if a specific column is present or not.
Why don't you use LinqToSql - everything you need is done automatically. For the sake of being general you can use any other ORM tool for .NET
If you don't want to use an ORM you can also use reflection for things like this (though in this case because ProductID is not named the same on both sides, you couldn't do it in the simplistic fashion demonstrated here):
List Provider in C#
I would call reader.GetOrdinal for each field name before starting the while loop. Unfortunately GetOrdinal throws an IndexOutOfRangeException if the field doesn't exist, so it won't be very performant.
You could probably store the results in a Dictionary<string, int> and use its ContainsKey method to determine if the field was supplied.
I ended up writing my own, but this mapper is pretty good (and simple): https://code.google.com/p/dapper-dot-net/