Generic List is not coming - c#

This sample uses where to find all products that are out of stock.
public void Linq2()
{
List<Product> products = GetProductList();
var soldOutProducts =
from p in products
where p.UnitsInStock == 0
select p;
Console.WriteLine("Sold out products:");
foreach (var product in soldOutProducts)
{
Console.WriteLine("{0} is sold out!", product.ProductName);
}
}
Result:
Sold out products:
Chef Anton's Gumbo Mix is sold out!
Alice Mutton is sold out!
Thüringer Rostbratwurst is sold out!
Gorgonzola Telino is sold out!
Perth Pasties is sold out!
The above example i got from MSDN Samples, this is Simple2, the problem is when I enter List<Products>, Products is not showing in Intellisense. When I enter it manually, I get the following error:
Only assignment, call, increment, decrement and new object expression
can be used as a statement
What can I do to solve this?

Ok,
your problem is that you copied the linked source. But this source does not contain the definitions for neither Product nor GetProductList()
Please take a look at the example here - it has everything you need:
List<string> fruits =
new List<string> { "apple", "passionfruit", "banana", "mango",
"orange", "blueberry", "grape", "strawberry" };
IEnumerable<string> query = fruits.Where(fruit => fruit.Length < 6);
foreach (string fruit in query)
{
Console.WriteLine(fruit);
}

That's because you don't have the class defined. You to add the class definition. You could write the class in the same file, add a new class file and put the definition of Product in it.

Related

Trouble creating a third list using items from two lists

I'm trying to put together a list (let's call this FinalList) using the combined values of two lists: Customers and Products. Suppose we have four Customers and one Product, FinalList should have a final result of four items (one for each customer).
For example:
Customer List:
Customer Code | Customer Name | Customer Branch ID
------------------|-----------------------|------------------------
001 | Tom | T001
002 | Dick | T002
003 | Harry | T003
004 | Jerry | T004
Product List:
Product Code | Product Name
------------------|---------------------
P001 | Apple
Currently I'm trying to do it this way:
var finalList = new List<ProductDetailDto>();
var customerList = new List<CustomerGroup>();
/// productsList is also type List<ProductDetailDto>();
for (var j = 0; j<= productsList.Count()-1; j++)
{
for (int i = 0; i <= customerList.Count() - 1; i++)
{
var singleDetail = new ProductDetailDto();
// Copy current products to groupDetail
singleDetail = productsList[j];
// Assemble rest of the info
singleDetail.CustCode = customerList[i].Customer.CustomerCode;
singleDetail.CustName = customerList[i].Customer.CustomerName;
singleDetail.CustBranchId = customerList[i].Customer.CustomerBranchId;
finalList.Add(singleDetail);
}
}
return finalList;
After executing this however, finalList only used Jerry as customer for all four items. I tried using foreach as well with the same results. I'm not really sure what I did wrong here, and I'm embarrassed that this seems basic to some, so I'm hoping for a fresh set of eyes to spot what mistake I made here...
Also, is there any way I can further optimize this?
Any help will be greatly appreciated, as always. Thank you.
Here:
// Copy current products to groupDetail
singleDetail = productsList[j];
You don't actually copy current product, but you copy a reference to your item from productsList, and on every inner loop iteration you override properties in the same productsList[j] element.
You may want to read more on how assignment works on reference types:
https://www.microsoftpressstore.com/articles/article.aspx?p=2454676
You need to create a new object if you want to make a cross product of two lists:
var finalList = new List<ProductDetailDto>();
var customerList = new List<CustomerGroup>();
/// productsList is also type List<ProductDetailDto>();
for (var j = 0; j<= productsList.Count()-1; j++)
{
for (int i = 0; i <= customerList.Count() - 1; i++)
{
var singleDetail = new ProductDetailDto
{
ProductCode = productsList[j].ProductCode,
ProductName = productsList[j].ProductName
// and whatever other properties your product have
};
// Assemble rest of the info (these can actually go to object initializer too)
singleDetail.CustCode = customerList[i].Customer.CustomerCode;
singleDetail.CustName = customerList[i].Customer.CustomerName;
singleDetail.CustBranchId = customerList[i].Customer.CustomerBranchId;
finalList.Add(singleDetail);
}
}
return finalList;
As for me, it is confusing that you have properties like CustCode, CustName and CustBranchId in your ProductDetailDto. Are these properties just empty for objects in productsList? Consider creating another class specially for these needs like CustomerProductDto, so that your intention becomes more clear.
You can optimize this using LINQ:
var items = from p in productsList
from c in customerList
select new ProductDetailDto
{
ProductCode = p.ProductCode,
ProductName = p.ProductName
CustCode = c.Customer.CustomerCode,
CustName = c.Customer.CustomerName,
CustBranchId = c.Customer.CustomerBranchId,
};
return items.ToArray();
This line of code:
singleDetail = productsList[j];
affects a pointer and not values, so in the end you have a list of the same pointer so you have only the last modification repeated customerList.Count()
So you must add the values one by one like customerList

difference between List<T> and List<T>=new List<T> in c# [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am sorry if my question is silly, i am new to c#
I want to know what is the exact difference between when we create a List variable like this
List<T> lstStudents;
and when we create a list like this
List<T>= new List<T>();
i just found out that even if we create a variable without intializing an object to it, still we would be able to add new objects, if it is so then what is the difference between this two
let me explain the scenario with some code which i was trying
List<Product> product = new List<Product> {
new Product() { ProductID = 1, ProductName = "A" }
, new Product() { ProductID = 2, ProductName = "B" }
, new Product() { ProductID = 3, ProductName = "C" }
, new Product() { ProductID = 4, ProductName = "D" }
, new Product() { ProductID = 5, ProductName = "E" }
};
now if i add a variable like this
List<Product> p = product;
I am still able to add objects in this variable
p.Add(new Product { ProductID = 3 });
Please clarify my doubt.
Thank you
I am sorry may be i am doing something wrong in this code
public class Students
{
public string Name { get; set; }
public int StudentId { get; set; }
}
List<Product> product = new List<Product> {
new Product() { ProductID = 1, ProductName = "A" }
, new Product() { ProductID = 2, ProductName = "B" }
, new Product() { ProductID = 3, ProductName = "C" }
, new Product() { ProductID = 4, ProductName = "D" }
, new Product() { ProductID = 5, ProductName = "E" }
};
List<Product> p = product;
p.Add(new Product { ProductID = 3 });
when i run this i get 6 items instead of 5
now if i add a variable like this
List<Product> p = product;
I am still able to add objects in this variable
Yes, because the variables are referencing the same list. If you look at p you will notice that the added item is reflected there as well.
i just found out that even if we create a variable without intializing an object to it, still we would be able to add new objects
Not true - if you do this:
List<T> lstStudents;
and try to add something:
lstStudents.Add(...);
You will get a compiler error if the list declaration is within a method, and a NullReferenceException if it a class member because lstStudents is not referencing anything (it is a "null" reference).
when i run this i get 6 items instead of 5
Yes because the list referenced by product contained 5 elements, p references the same list, and you added one.
Lists are reference types, meaning that "copying" the value of one variable to another variable only copies a reference to the underlying object. It's akin to pointers in older languages like C.
List<T> lstStudents;
Is null and:
List<T> lstStudents = new List<T>();
Is an empty list. Example:
List<T> lstStudents;
lstStudents.add(new Student("Bob")); // this will throw a null exception
List<T> lstStudents = new List<T>();
lstStudents.add(new Student("Bob")); // this work just fine
Also, as mentioned above:
List<T>= new List<T>();
Is an erroneous syntax due to the fact that you are not assigning a variable name.
So it looks like you have 3 different ways of "creating" a list going on.
List<T> lstStudents;
This creates a list, but it doesn't actually "point" to anything. It is null. If you try and add items to it you will get a null reference exception.
List<T> listStudents = new List<T>();
This creates a new list in memory. It's empty and you can add items to it as per normal.
List<T> list1 = new List<T>() { // Add some items here};
List<T> list2 = list1;
Student newStudent = new Student();
list2.add(newStudent);
list1.Contains(newStudent); // This equals true.
Now this is where I think you may be getting confused. A List is a reference variable in C#. That means that two different pointers can point to the same list. In the example above, we've created our first list and added some items. In the next line we've created a second list but "pointed" it to the first list. We then add a new student to the second list, and magically it shows up in the first list? How? It's because the first and second list are actually the same. They just have two different pointers to the same space in memory.
For more reading on Reference types, here is the official MSDN documentation : https://msdn.microsoft.com/en-us/library/490f96s2.aspx

The right way to insert multiple records to a table using LINQ to Entities

As many of us have done, I set up a simple loop to add multiple records from a databse. A prototypical example would be something like this:
Method I:
// A list of product prices
List<int> prices = new List<int> { 1, 2, 3 };
NorthwindEntities NWEntities = new NorthwindEntities();
foreach (int price in prices)
{
Product newProduct = new Product();
newProduct.Price = price;
NWEntities.Products.AddObject(newProduct);
}
NWEntities.SaveChanges();
When I first set up the loop, however, I intuitively wrote:
Method II:
Product newProduct = new Product();
foreach (int price in prices)
{
newProduct.Price = price;
NWEntities.Products.Add(newProduct);
}
After doing a little reading, several individuals mentioned that if the Method II is used only one record would be added to the table. This seems counter intuitive. It's the Add() function which load a new insertion, and, I would think, creates an object after each call with the data passed in. Declaring my Product object outside the loop would seem to better utilize resources, as the only overhead consumed in each call would be the re-assignment of the object instance property, and not the re-construction of the object instance itself.
Can anyone please clarify? I could not find another post that deals with this question directly. If one is out there please point to it.
Simply move the instantiation of the new Product inside the loop. Your code as it is written will add a single instance multiple times which does not produce what you are after...you need a separate instance of each product...the Add method does not make a copy, it attaches the object to the context and marks it for insertion.
foreach (int price in prices)
{
Product newProduct = new Product();
newProduct.Price = price;
NWEntities.Products.Add(newProduct);
}
To see what is happening a bit more explicity consider the following:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Try to reuse same Instance:");
using (var ctx = new AdventureWorksEntities())
{
List<int> ids = new List<int> {1, 2, 3};
Product p1 = new Product();
Product reference = p1;
Product p2;
Console.WriteLine("Start Count: {0}", ctx.Products.Count());
foreach (var id in ids)
{
p1.ProductID = id;
p2 = ctx.Products.Add(p1);
Console.WriteLine("p1 = p2 ? {0}", p1 == p2);
Console.WriteLine("p2 = reference? {0}", p2 == reference);
Console.WriteLine("State: {0}", ctx.Entry(p1).State);
var changes = ctx.ChangeTracker.Entries<Product>();
Console.WriteLine("Change Count: {0}", changes.Count());
}
}
Console.WriteLine();
Console.WriteLine("Distinct Instances:");
using (var ctx = new AdventureWorksEntities())
{
List<int> ids = new List<int> { 1, 2, 3 };
Product p2;
foreach (var id in ids)
{
var p1 = new Product {ProductID = id};
p2 = ctx.Products.Add(p1);
Console.WriteLine("p1 = p2 ? {0}", p1 == p2);
Console.WriteLine("State: {0}", ctx.Entry(p1).State);
var changes = ctx.ChangeTracker.Entries<Product>();
Console.WriteLine("Change Count: {0}", changes.Count());
}
}
Console.ReadLine();
}
}
In the first loop you are reusing the same product instance, but when you add it to the context you are just using the same reference each time. You can see that the change count remains at 1 regardless of how many times the loop is executed. Of course only the last values would be saved if you were to call ctx.SaveChanges().
In the second version, the change count is correctly incremented each time and you would be calling SaveChanges would save all of distinct entities as you would expect.
+1 For Terryt's answer. You need to stick with method one or something similar.
In Entity framework 6 version, there is a new method to add a set of data in a single statement. This is the AddRange Method.
I would like to add that I find the AddRange method elegant when you want to add entities based on an existing list (or IEnumerable).
In your case it could be done somewhat like this:
NWEntities.Products.AddRange(
Prices.Select(priceitem =>
new Product{price = priceitem})
)
Semantically this should be similar to your method 1. One Product object is instanciated per price in the price list. There is however one difference, it is done anonymously, so there are no explicit defined reference variables pointing to the new object.
If performance is important then this question might give you some further information: Fastest Way of Inserting in Entity Framework
Hope this give you some help.
We wouldn't need the help of loop. We can do this by linq. As by the below code, names are have to add into Employee table from the nameList with the bit field IsDeleted.
db.Employee.AddRange(
nameList.Select(name =>
new Employee
{
Name = name,
IsDeleted = false
})
);
I had a similar problem. In my issue, I had this code:
var cratelist = db.TruckContainerLoads.Where(x => x.TruckID == truckid).Select(x => x.ContainerID);
if (!cratelist.Any())
{
return;
}
foreach (var crateid in cratelist) {
TruckContainerLoad crInstance = new TruckContainerLoad();
crInstance.ContainerID = crateid;
try
{
db.TruckContainerLoads.Add(crInstance);
db.SaveChanges();
}
catch
{
return;
}
}
My query only added the first record in my foreach. The issue was that I needed to call my db.SaveChanges() outside of the foreach loop, after adding multiple records. For me, the answer to my issue was actually in the question. So, I'm upvoting the question.

Using First() get the 2nd item of LINQ result?

I'm new to Linq and EntityFramework. This is a sample program I met while learning them.
The data in table is like this:
BlogId Title
1 Hello Blog
2 New Blog
3 New Blog
I have the following Linq code, trying to read the first blog id(expected to be 2):
var name = "New Blog";
var blogs = (from b in db.Blogs
where b.Title == name
orderby b.Title
select b);//.ToList();
Console.Write("The first id: ");
Console.WriteLine(blogs.First().BlogId);
The result comes out to be 3.
Then I use ToList():
var blogs = (from b in db.Blogs
where b.Title == name
orderby b.Title
select b).ToList();
Console.Write("The first id: ");
Console.WriteLine(blogs.First().BlogId);
The result comes out to be 2.
Can anyone help to explain this? Or is this a bug?
Thanks.
//////////////////////// UPDATE /////////////////////////////
I just deleted the data in the database and inserted some new items. Now the table is like this:
BlogId Title
5 New Blog
6 New Blog
7 New Blog
8 New Blog
Then I ran the program above(Not with ToList()), the First() method returns the id 6
So I assume the method always returns the 2nd item in the situation above. And it doesn't seem to have anything to do with the RDBMS. Can anyone explain?
Thanks.
/////////////////////////////////////////////////////
FYI, the following is the whole .cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
namespace SampleNew
{
class Program
{
public class Blog
{
[Key]
public Int32 BlogId { get; set; }
public String Title { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Post
{
[Key]
public Int32 PostId { get; set; }
public String Title{ get; set; }
public String Content { get; set; }
}
public class BlogContext : DbContext
{
public DbSet<Blog> Blogs{ get; set; }
public DbSet<Post> Posts { get; set; }
}
static void Main(string[] args)
{
using (var db = new BlogContext())
{
// Create and save a new Blog
// Console.Write("Enter a name for a new Blog: ");
var name = "New Blog";
//var blog = new Blog { Title = name };
var blogs = (from b in db.Blogs
where b.Title == name
orderby b.Title
select b).ToList();
Console.Write("The first id: ");
Console.WriteLine(blogs.First().BlogId);
Console.WriteLine(blogs.Count());
Blog blog = null;
foreach (Blog b in blogs)
{
blog = b;
Console.WriteLine(blog.BlogId);
}
Console.WriteLine(blog.BlogId);
Console.WriteLine(blogs.First().BlogId);
Console.WriteLine(blogs.First().BlogId);
Console.WriteLine(blogs.Last().BlogId);
Console.WriteLine(blogs.Last().BlogId);
blog.Posts = new List<Post>();
var post = new Post { Content = "Test Content2", Title = "Test Title2"};
blog.Posts.Add(post);
db.Posts.Add(post);
db.SaveChanges();
// Display all Blogs from the database
var query = from b in db.Blogs
orderby b.Title
select b;
Console.WriteLine("All blogs in the database:");
foreach (var item in query)
{
Console.WriteLine(item.Title);
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}
}
You've got two identical titles there, but with different IDs. Your RDBMS has the flexibility of returning the rows that correspond to your 'New Blog' in any order that it wishes, because your code does not specify anything beyond the requirement to order by the title. Moreover, it is not even required to return results in the same order each time that you run the same query.
If you would like predictable results, add a "then by" to your LINQ statement to force the ordering that you wish to have:
var query = from b in db.Blogs
orderby b.Title, b.BlogId
select b;
EDIT :
When I ran the program above, the First() method returns the id 6 so I assume the method always returns the 2nd item in the situation above. And it doesn't seem to have anything to do with the RDBMS. Can anyone explain?
That's also happening in RDBMS, and it is reproducible without LINQ. Here is a small demo (link to sqlfiddle):
create table blogs(blogid int,title varchar(20));
insert into blogs(blogid,title) values (5,'New blog');
insert into blogs(blogid,title) values (6,'New blog');
insert into blogs(blogid,title) values (7,'New blog');
insert into blogs(blogid,title) values (8,'New blog');
SELECT * FROM Blogs ORDER BY Title
This query produces results in "natural" order:
BLOGID TITLE
------ --------
5 New blog
6 New blog
7 New blog
8 New blog
However, this query, which is what EF runs to get the First() item in RDBMS
SELECT TOP 1 * FROM Blogs ORDER BY Title
returns the second row in natural order:
BLOGID TITLE
------ --------
6 New blog
It does not mean that it is going to return the same row in other RDBMSs (link to a demo with MySQL returning a different row for the same query), or even in the same RDBMS. It simply demonstrates that LINQ relies on RDBMS for the selection of the row, and the RDBMS returns an arbitrarily selected row.
I suspect the difference comes in the optimizations that are taken by First() without the ToList().
When you call ToList(), the entire ordered list must be created. So it will order everything using an efficient sort algorithm.
However, with First(), it only needs to find the min value. So it can use a much more effecient algorithm that basically goes through the enumerable once and stores the current min object value. (So it will result in the first object of the min value).
This is a different algorithm then sorting the entire list and hence gets a different result.
Update:
Also, this being a database, it may be using linq to sql which will produce a different query based on the above description (getting a sorted list vs getting the first with the min value).

C# - Combine multiple LINQ collections with same properties

Maybe it's late in the night, but I'm stumped here. I'm trying to combine multiple lists with the same properties into one. I thought that LINQ's .UNION would do the trick but I was mistaken. Here's an example of a few of my lists:
LIST1 (report names):
Date Name Title Product
02/01/13 Steve Hello World Report
02/05/13 Greg Howdy Report
LIST2 (song names):
Date Name Title Product
01/01/13 John Time Song
01/05/13 Bob Sorry Song
LIST3 (games names):
Date Name Title Product
12/01/12 Google Bike Race Game
12/05/12 Apple Temple Run Game
My class is very simple. Here's what it looks like:
public class MyClass {
public DateTime Date { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public string Product { get; set; }
}
In case you're wondering, I used this LINQ query to get one of the above lists:
var finalList = Games
.Select (s => new MyClass {
Date = (System.DateTime) s.Games.Creation_date,
Name = s.Games.Last_name,
Title = string.Format("{0} (Report)", s.Game.Headline),
Product="Report"
})
;
So far, it's pretty easy, but I want to combine all my lists into 1. So, my final list should look like:
Date Name Title Product
02/01/13 Steve Hello World Report
02/05/13 Greg Howdy Report
01/01/13 John Time Song
01/05/13 Bob Sorry Song
12/01/12 Google Bike Race Game
12/05/12 Apple Temple Run Game
I thought that a UNION command would do it:
var newList = List1.Union(List2).Union(List3);
But I'm not getting the desired output.
Date Name Title Product
02/01/13 Steve Hello World Report
02/05/13 Greg Howdy Report
01/01/13 Bob Time Game
01/05/13 John Sorry Song
12/01/12 Google Bike Race Song
12/05/12 Apple Temple Run Game
Any idea on what I'm doing wrong here?
Try:
list1.Concat(list2).Concat(list3);
You don't want to be using Union ( working or not) anyway as it does set union.
You could try using the AddRange command should look something like this
var FullList = list1.AddRange(list2).AddRange(list3);
or the fail safe way whould be
var FullList = list1.Concat(list2).Concat(list3).ToList(); //Personally i would use this
or you also have
var FullList = new[] { list1, list2, list3 }.SelectMany(a => GetAllProducts(a)).ToList();

Categories

Resources