Create a list with LINQ - c#

I have an class called message, inside which I have a IEnumerable called copies.
I need to create a new Recipient class object with the copies content.
In order to do that, I created a Recipient list, then interacting on copies using ForEach method; But I took so much code lines, and it doesn't feel good for me. There is a way to do that using LINQ methods?
I'll put below what I've done so far.
CODE USING FOREACH (PROPERLY WORKING)
var recipientListWithForEach = new List<Recipient>();
foreach (var item in message.Copies)
{
recipientListWithForEach.Add(new Recipient
{
EmailAddress = new EmailAddress
{
Address = item
}
});
}
CODE USING LINQ (NOT WORKING, IDK WHY)
var recipientListWithLINQ = new List<Recipient> {
message.Copies.Select(item => new Recipient {
EmailAddress = new EmailAddress {
Address = item
}
});
};
Giving the error message:
not possible convert from "System.Collections.Generic.IEnumerable<Microsoft.Graph.Recipient>" to "Microsoft.Graph.Recipient"

Actually problem that you have not used proper constructor for List
// working
new List<T>(items)
Following is list initialisation syntax, which accepts not an IEnumerable but single items separated by coma.
// bad
new List<T> {items}
// working
new List<T> {item1, item2}
So, just correct your code
var recipientListWithLINQ = new List<Recipient> (
message.Copies.Select(item => new Recipient {
EmailAddress = new EmailAddress {
Address = item
}
));
};
But LINQ query should be simplier
var recipientListWithLINQ =
message.Copies.Select(item => new Recipient {
EmailAddress = new EmailAddress {
Address = item
}
)
.ToList();

You're doing a little bit too much work! .Select returns the list you need. Wrapping that list in a Recipient constructor is not needed.
var recipientListWithLINQ =
message.Copies.Select(item => new Recipient {
EmailAddress = new EmailAddress {
Address = item
}
});

Update per comment: since you need single item, you don't really need IEnumerable. Just pick first item from Copies and construct your Recipient. And probably pick a better name for a variable?
var item = message.Copies.First();
var recipientListWithLINQ = new Recipient {
EmailAddress = new EmailAddress {
Address = item
}
};
Original answer:
You need to convert your IEnumerable to List with ToList()
var recipientListWithLINQ = message.Copies.Select(item => new Recipient {
EmailAddress = new EmailAddress {
Address = item
}
}).ToList();

Related

Insert collection into List from MongoDB

I try to get all data from collection into MongoDB server using C# driver.
The idea is connect to the server and get all collection than insert into list of class.
List<WatchTblCls> wts;
List<UserCls> users;
List<SymboleCls> syms;
public WatchTbl()
{
InitializeComponent();
wts = new List<WatchTblCls>();
users = new List<UserCls>();
syms = new List<SymboleCls>();
}
public async void getAllData()
{
client = new MongoClient("mongodb://servername:27017");
database = client.GetDatabase("WatchTblDB");
collectionWatchtbl = database.GetCollection<WatchTbl>("Watchtbl");
collectionUser = database.GetCollection<UserCls>("Users");
collectionSymbole = database.GetCollection<SymboleCls>("Users");
var filter = new BsonDocument();
using (var cursor = await collectionWatchtbl.FindAsync(filter))
{
while (await cursor.MoveNextAsync())
{
var batch = cursor.Current;
foreach (var document in batch)
{
wts.Add(new WatchTblCls(document["_id"], document["userId"], document["wid"], document["name"], document["Symboles"]));
}
}
}
}
I get this error under
wts.Add(new WatchTblCls(document["_id"], document["userId"], document["wid"], document["name"], document["Symboles"]));
Cannot apply indexing with [] to an expression of type 'WatchTbl'
I don't understand the reason behind using WatchTbl and WatchTblCls both together. Is WatchTblCls a model for the entity WatchTbl here? Im not sure.
In any case. If you go for aggregation and want to convert WatchTbl collection to WatchTblCls list, your desired solution might look like the following. I don't know the defiitions of the classes so I'm assuming:
var client = new MongoClient("mongodb://servername:27017");
var database = client.GetDatabase("WatchTblDB");
var collectionWatchtbl = database.GetCollection<WatchTbl>("Watchtbl");
var collectionUser = database.GetCollection<UserCls>("Users");
var collectionSymbole = database.GetCollection<SymboleCls>("Users");
var list = collectionWatchtbl.AsQueryable().Select(x => new WatchTblCls() {
id = x.id,
userId = x.userId,
.....
});
If you can use the same WatchTbl class and still want to load the full collection to a local List (which is definitely not a good idea):
List<WatchTbl> list = await collectionWatchtbl.Find(x => true).ToListAsync();

How to combine two c# objects using Linq

I am trying to combine two LIKE objects together and remove duplicates.
Tried this
This didn't work
Here is my object [simple]
public class LabelItem
{
public string LabelName { get; set; }
public string LabelValue { get; set; }
}
my data call returns the same object type
public static List<LabelItem> ReturnControlLabelList(Enums.LanguageType languageType, string labelList = "")
I pass this to the method
string[] LABELLIST = new string[] { "foxLabel", "commonLabel" };
var helper = new LabelHelper(, LABELLIST);
this is where I get null
public LabelHelper(Enums.LanguageType languageType, string[] labelListName)
{
if (labelListName != null)
{
List<LabelItem> labels = new List<LabelItem>();
this.LabelList = new List<LabelItem>();
foreach (var name in labelListName)
{
labels = DBCommon.ReturnControlLabelList(languageType, name);
this.LabelList.Concat(labels).Distinct().ToList();
}
}
else
{
this.LabelList = null;
}
}
public List<LabelItem> LabelList { get; private set; }
The concat is not working. I keep getting count 0 for labels and I can see the returns come back with 275 and 125 in the for loop.
Thanks in advance for the help.
Still having an issue
I want to use the suggestion from below but am still struggling.
The string[] passed in will get two lists of labelitems that are not unique when joined together in the loop. I need the distinct of the multiple lists returned in this.LabelList.
I got it to work with this but...I'm sure it's crazy inefficient.
Thanks for the help.
this.LabelList = new List<LabelItem>();
foreach (var name in labelListName)
{
var ret = DBCommon.ReturnControlLabelList(languageType, name);
this.LabelList = this.LabelList.Concat(ret).Distinct().ToList();
}
var distinctList = this.LabelList.GroupBy(x => new { x.LabelName, x.LabelValue })
.Select(x => x.FirstOrDefault());
this.LabelList = new List<LabelItem>();
foreach (var item in distinctList)
{
this.LabelList.Add(item);
Debug.WriteLine(item.LabelName + ' ' + item.LabelValue);
}
}
this.LabelList.Concat(labels).Distinct().ToList(); without assigning it to something doesn't make much sense. LINQ query does not modify the source collection, it returns a new one, so you'd have to assign it back to this.LabelList if you want it to get updated:
this.LabelList = this.LabelList.Concat(labels).Distinct().ToList();
You should be aware, that it's highly inefficient solution, and you should go with something based on SelectMany:
this.LabelList
= labelListName.SelectMany(name => DBCommon.ReturnControlLabelList(languageType, name)
.Distinct()
.ToList();
Concat and most other linq methods return an IEnumerable which you then need to do something with. It will not change your existing list so you need to just assign it with:
this.LabelList = this.LabelList.Concat(labels).Distinct().ToList();

Insert rows using Linq

Can anyone tell where I make a mistake ? :( I want to insert a row using this. It's just not working. I also tried to use "context.SaveChanges();" but nothing changed. No insert at all, and no exception.
public List<string> Add_Address(string address, int selected_item)
{
List<string> list = new List<string>();
using(var context = new RSS_Reader_Database())
{
Address Address = new Address();
Category_Address Category_Address = new Category_Address();
Address.URL = address.ToString();
int max_id = Convert.ToInt32(context.Addresses.OrderByDescending(t => t.ID_Address).FirstOrDefault());
Category_Address.ID_Address = max_id;
Category_Address.ID_Category = selected_item+1;
var select_query = from t in context.Addresses select t.URL;
foreach (var element in select_query)
{
list.Add(element);
}
}
return list;
}
Edit: Following all Your advices, I made something that works. Looking at this code above, I have no idea what I was trying to do yesterday. Thanks a lot.
public List<string> Add_Address(string address, int selected_item)
{
List<string> list = new List<string>();
using(var context = new RSS_Reader_Database())
{
Address Address = new Address() { URL = address };
context.Addresses.Add(Address);
context.SaveChanges();
int max_id = context.Addresses.Max(u => u.ID_Address);
Category_Address Category_Address = new Category_Address() { ID_Address = max_id, ID_Category = selected_item + 1 };
context.Categories_Addresses.Add(Category_Address);
context.SaveChanges();
var query = from t in context.Addresses
select t.URL;
var data = query.ToList();
foreach (var element in data)
{
list.Add(element);
}
}
return list;
}
Saving with Entity Framework generally works like this. Using your above code as a starting point.
using(var context = new RSS_Reader_Database())
{
Address address = new Address();
// Set address properties
context.Addresses.Add(address);
context.SaveChanges();
}
You need to add the object to the DbSet<T> where T is the type of the entity that is defined on the DbContext. You then need to call SaveChanges() on the context.
I would suggest reading this. It is an easy to follow introduction to Entity Framework.
Not sure exactly what you are trying to do.
But if you are expecting to insert the data by the list.Add(element); command it won't work.
If you are planning to insert data into the same DB, you need to use one property from the context to represent the List collection add a new element on this property.
Something like:
context.Lists.Add(element);
if you want retrieve data, you should not call SaveChanges() !,
try get all values from one query like this:
List<string> select_query = (from t in context.Addresses select t.URL).ToList();

How to add one List into another List

I am trying to add one list into another but it is giving me error of The best overloaded method match for 'System.Collection.Generic.List.AddRange(System.Collections.Generic.IEnumerable)' has some invalid arguments
My code is:
public ActionResult RegisteredEvent(string Cno)
{
if (Request.IsAjaxRequest())
{
List<tblEvent> eventlist = new List<tblEvent>();
List<RegisteredEvent> list = new List<RegisteredEvent>();
var db = new clubDataContext();
int[] eventIds = (from m in db.EventRegistrations where m.Cno == Cno select m.Event_Id).ToArray();
int i = 1;
foreach (var item in eventIds)
{
list = (from m in db.tblEvents
where item.Equals(m.EventId)
select new RegisteredEvent()
{
id = m.EventId,
caption = m.Caption,
description = m.Description,
date = m.Date.ToString()
}).ToList();
eventlist.AddRange(list); //Here I am getting error
}
ViewBag.eventDetail = eventlist;
return PartialView("RegisteredEvent");
Simply speaking, you can only concatenate lists of the same type.¹
eventlist is a List<tblEvent>
list is a List<RegisteredEvent>
¹ This is not entirely correct: Since IEnumerable is covariant, it is actually possible to add entries of a List<S> to a List<T>, if S is a subtype of T.
The T in List<T> needs to have the same type or inherent from the same base type
List<RegisteredEvent> eventlist
List<RegisteredEvent> list
or
List<tblEvent> eventlist
List<tblEvent> list
You can use IEnumerable.Select as this (I don't know the structure of tblEvent, so adapt this at your code.
eventlist.AddRange(list.Select(x => new tblEvent{ id = x.id, caption = x.caption, ... }));
But the best way is to create directly a tblEvent
//the list sent to View
eventlist = (from m in db.tblEvents
where item.Equals(m.EventId)
select new tblEvent() //here
{
id = m.EventId,
caption = m.Caption,
description = m.Description,
date = m.Date.ToString()
}).ToList();

Cannot implicitly convert type '.List<AnonymousType#1>' to '.List<WebApplication2.Customer>'

In the following code that returns a list:
public List<Customer> GeAllCust()
{
var results = db.Customers
.Select(x => new { x.CustName, x.CustEmail, x.CustAddress, x.CustContactNo })
.ToList()
return results;
}
I get an error reporting that C# can't convert the list:
Error: Cannot implicitly convert type System.Collections.Generic.List<AnonymousType#1> to System.Collections.Generic.List<WebApplication2.Customer>
Why is that?
Here's a screenshot showing some additional information that Visual Studio provides in a tooltip for the error:
Is it right way to return some columns instead of whole table....?
public object GeAllCust()
{
var results = db.Customers.Select(x => new { x.CustName, x.CustEmail, x.CustAddress, x.CustContactNo }).ToList();
return results;
}
When you look the code:
x => new { ... }
This creates a new anonymous type. If you don't need to pull back only a particular set of columns, you can just do the following:
return db.Customers.ToList();
This assumes that Customers is an IEnumerable<Customer>, which should match up with what you are trying to return.
Edit
You have noted that you only want to return a certain subset of columns. If you want any sort of compiler help when coding this, you need to make a custom class to hold the values:
public class CustomerMinInfo
{
public string Name { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public int? ContactNumber { get; set; }
}
Then change your function to the following:
public List<CustomerMinInfo> GetAllCust()
{
var results = db.Customers.Select(x => new CustomerMinInfo()
{
Name = x.CustName,
Email = x.Email,
Address = x.Address,
ContactNumber = x.CustContactNo
})
.ToList();
return results;
}
This will work, however, you will lose all relationship to the database context. This means if you update the returned values, it will not stick it back into the database.
Also, just to repeat my comment, returning more columns (with the exception of byte arrays) does not necessarily mean longer execution time. Returning a lot of rows means more execution time. Your function is returning every single customer in the database, which when your system grows, will start to hang your program, even with the reduced amount of columns.
You are selecting to an anonymous type, which is not a Customer.
If you want to do (sort of) this, you can write it like this:
return db.Customers.Select(x => new Customer { Name = x.CustName, Email = x.CustEmail, Address = x.CustAddress, ContactNo = x.ContactNo }).ToList();
This assumes the properties on your Customer object are what I called them.
** EDIT ** Per your comment,
If you want to return a subset of the table, you can do one of two things:
Return the translated form of Customer as I specified above, or:
Create a new class for your business layer that only has only those four fields, and change your method to return a List<ShrunkenCustomer> (assuming ShunkenCustomer is the name that you choose for your new class.)
GetAllCust() is supposed to return a List of Customer, Select New will create a list of Anonymous Types, you need to return a list of Customer from your query.
try:
var results = db.Customers.Select( new Customer{CustName = x.CustName}).ToList(); //include other fields
I guess Customer is a class you have defined yourself?
The my suggestion would be to do something like the following:
var results = db.Customers.Select(x => new Customer(x.Custname, x.CustEmail, x.CustAddress, x.CustContactNo)).ToList();
The reason is that you are trying to return a list of Customer but the results from your link is an anonymous class containing those four values.
This would of course require that you have a constructor that takes those four values.
Basically whatever u got in var type, loop on that and store it in list<> object then loop and achieve ur target.Here I m posting code for Master details.
List obj = new List();
var orderlist = (from a in db.Order_Master
join b in db.UserAccounts on a.User_Id equals b.Id into abc
from b in abc.DefaultIfEmpty()
select new
{
Order_Id = a.Order_Id,
User_Name = b.FirstName,
Order_Date = a.Order_Date,
Tot_Qty = a.Tot_Qty,
Tot_Price = a.Tot_Price,
Order_Status = a.Order_Status,
Payment_Mode = a.Payment_Mode,
Address_Id = a.Address_Id
});
List<MasterOrder> ob = new List<MasterOrder>();
foreach (var item in orderlist)
{
MasterOrder clr = new MasterOrder();
clr.Order_Id = item.Order_Id;
clr.User_Name = item.User_Name;
clr.Order_Date = item.Order_Date;
clr.Tot_Qty = item.Tot_Qty;
clr.Tot_Price = item.Tot_Price;
clr.Order_Status = item.Order_Status;
clr.Payment_Mode = item.Payment_Mode;
clr.Address_Id = item.Address_Id;
ob.Add(clr);
}
using(ecom_storeEntities en=new ecom_storeEntities())
{
var Masterlist = en.Order_Master.OrderByDescending(a => a.Order_Id).ToList();
foreach (var i in ob)
{
var Child = en.Order_Child.Where(a => a.Order_Id==i.Order_Id).ToList();
obj.Add(new OrderMasterChild
{
Master = i,
Childs = Child
});
}
}

Categories

Resources