Select Distinct User ID in a ViewModel List - c#

I'm pretty new to MVC so there might be a super simple answer to this.
The following is my current controller code:
public class StudentBanController : Controller
{
SWGS_GlobalDataEntities DataContext = new SWGS_GlobalDataEntities();
// GET: StudentBan
public ActionResult DisplayBans()
{
var theData = DataContext.tblGlobalLogOnLogOffStudentBans.ToList();
List<StudentBanDisplayViewModel> BanList = theData
.Select(viewModel => new StudentBanDisplayViewModel
{
ID = viewModel.ID,
UserID = viewModel.UserID,
StartBan = viewModel.StartBan,
EndBan = viewModel.EndBan
}).Where(b => b.EndBan > DateTime.Today).ToList();
return PartialView(BanList);
}
}
What I am trying to do is create a list, but I only want it to contain records for Distinct UserID's and I cant figure how to do it.
I have tried .distinct in various places and also grouping by user ID and selecting .first but nothing seems to do the job.
Any advice?

Try the following
List<StudentBanDisplayViewModel> BanList = theData
.Select(viewModel => new StudentBanDisplayViewModel
{
ID = viewModel.ID,
UserID = viewModel.UserID,
StartBan = viewModel.StartBan,
EndBan = viewModel.EndBan
}).Where(b => b.EndBan > DateTime.Today)
.DistinctBy(s => new {s.UserID}).ToList();
How to remove duplicates from collection using IEqualityComparer, LinQ Distinct
You will require the following
https://code.google.com/p/morelinq/source/browse/MoreLinq/DistinctBy.cs?r=d4396b9ff63932be0ab07c36452a481d20f96307

Related

How to get the entire list instead of only the first result? Net Core 3.1

The following functions return only the first row of the database, would you please guide me get the entire rows please?
My Function :
private List<Phrases_Clp> PhrasesStringToListPhrases_Clp(string phrases_codes)
{
List<Phrases_Clp> phrases_Clps = new List<Phrases_Clp>();
if (!String.IsNullOrEmpty(phrases_codes))
{
if (phrases_codes.Contains(","))
{
string[] listprhases = phrases_codes.Split(",");
foreach (var item in listprhases)
{
var mentiontoinsert = _context.Phrases_Clps.FirstOrDefault(m =>
m.Phrase_Numero == item);
phrases_Clps.Add(mentiontoinsert);
}
}
else
{
var mentiontoinsert = _context.Phrases_Clps.FirstOrDefault(m =>
m.Phrase_Numero == phrases_codes);
phrases_Clps.Add(mentiontoinsert);
}
}
return phrases_Clps;
}
UPDATE :
It still gives me the first result. I wonder if I should do changes in my view as I display information from another table which correspond the cell values in the current table.
Table Identification_Produit
Table Phrases Clp
Current Output:
Desired Output is to display 'Mentions Dangers' of each Product.
GET:
//GET: EvaluationRisque/Create
[Authorize(Roles = "Administrateur, Modificateur")]
public async Task<IActionResult> Create()
{
List<Models.dbo.equipements_protection.Equipement_Protection> listsequipement = _context.Equipement_Protections.ToList();
Create_Viewbags();
var model = new EvaluationRisquesViewModel();
var produitUtiliseByProduitId = await _context.Identification_Produit.FirstOrDefaultAsync();
model.MentionsDanger = produitUtiliseByProduitId;
model.List_Mentions_Danger = PhrasesStringToListPhrases_Clp(model.MentionsDanger.Mentions_Danger);
return View(model);
}
Bootstrap Model in the View Page:
<td>#foreach (var mention_danger in Model.List_Mentions_Danger)
{
<p> #mention_danger.Phrase_Numero : #mention_danger.Phrase_Libelle
</p>}
</td>
Change FirstOrDefault(...) to .Where(...).ToList() (or use phrases_Clps.AddRange( _context.Phrases_Clps.Where(...))).
But actually there is no need to make multiple requests to the database and you can skip conditional splitting, so something like following should work:
List<Phrases_Clp> phrases_Clps = null;
if (!string.IsNullOrEmpty(phrases_codes))
{
string[] listprhases = phrases_codes.Split(","); // will be array with one item if there are no commas in string
phrases_Clps = _context.Phrases_Clps
.Where(m => listprhases.Contains(m.Phrase_Numero))
.ToList();
}
return phrases_Clps ?? new List<Phrases_Clp>();
Because you are using FirstOrDefault function in this line:
var mentiontoinsert = _context.Phrases_Clps.FirstOrDefault(m => m.Phrase_Numero == item);
replace it with Where function.
Thinking that to utilize the query as IQueryable.
Updated:
Thanks for #GuruStron (Guru/Sensei)'s opinion and for pointing out the issue from my previous answer.
In short,
Exit the function with an empty List if phrases_codes is an empty string or null.
Working with IQueryable to prepare the different search criteria and defer the execution.
Once the query is prepared, execute the query via .ToList().
if (String.IsNullOrEmpty(phrases_codes))
return new List<Phrases_Clp>();
IQueryable<Phrases_Clp> query = _context.Phrases_Clps;
if (phrases_codes.Contains(","))
{
string[] listprhases = phrases_codes.Split(",");
query = query
.Where(x => listprhases.Contains(x.Phrase_Numero));
}
else
{
query = query
.Where(x => x.Phrase_Numero == phrases_codes);
}
return query.ToList();
This is my minimalist proposal
private List<Phrases_Clp> PhrasesStringToListPhrases_Clp(string phrases_codes)
{
var listprhases = phrases_codes != null ? phrases_codes.Split(",") : new string[0];
return _context.Phrases_Clps.Where(x => listprhases.Contains(x.Phrase_Numero)).ToList();
}

Invalid Operation Exception passing to View

I am trying, to no avail to display a dropdown list of all units a user doesnt already have. So i have List A with all Units and List B with all Units the user has. What i want is List C which is basically List A with List B removed from it. I have so far managed to filter out the data but i cant seem to display it in my View. All i get is a blank dropdown list. Can anyone see where im going wrong??
public ActionResult AddUnit(String usrCode)
{
var units = unitsClient.GetAllunits();
var allunitsCode = (from s in units select s.unitCode).ToList();
var thisUnitCode = (from s in db.Units
where s.UsrCode == usrCode
select s.UnitCode).ToList();
var notGot = allunitsCode.Except(thisUnitCode);
List<unitsummaryDTO> list = UnitList(units, notGot);
ViewBag.unitCode = new SelectList(list, "unitCode", "unitTitle");
var model = new UserUnit { UsrCode = usrCode };
return View("AddUnit", model);
}
private List<unitsummaryDTO> UnitList(unitsService.unitsDTO[] units, IEnumerable<string> notGot)
{
var allunits = unitsClient.GetAllunits();
var allunitsCode = (from s in allunits select s.unitCode).ToList();
IEnumerable<String> list1 = allunitsCode;
IEnumerable<String> list2 = notGot;
var listFinal = list1.Union(list2).toList;
return listFinal.Select(x => new unitsummaryDTO(){unitCode = x}).ToList();
}
This is my View model. But all i get is a blank drop down?? Can anyone help me out.
#model Projv1.UserUnit
#Html.HiddenFor(model => model.unitCode)
#Html.DropDownList("UnitCode")
It would be blank because #Html.DropDownList("UnitCode") doesn't have a source. If you look at MSDN for Html.DropDownList, the one your most likely trying to use is DropDownList(String, IEnumerable<SelectListItem>).
Your putting your select list into the ViewBag as unitCode so try:
#Html.DropDownList("Unit Code", ViewBag.unitCode);
A much easier way of handling this is to extend UserUnit as a ViewModel (or create something) to have the items needed by the SelectList on it and let MVC do the heavy lifting in the binding.
public class UserUnit
{
// ... other properties
IEnumerable<unitsummaryDTO> UnitCodes { get; set; }
public string MyUnitCode { get; set; }
}
Then
#Html.DropDownListFor(n => n.MyUnitCode,
new SelectList(Model.UnitCodes, "unitCode", "unitTitle"))

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
});
}
}

Please help me to return a list from my method

I am trying to get information from a database, convert it to a list and return the CustomerList. This first bit of code works fine. The second example is where I’m trying to accomplish the same thing except the fields are coming from my database. What’s wrong with what I’m doing and how can I make this work? The second piece of code works elsewhere in my project but not here.
private SchoolIn.Models.CustomerList CreateCustomerList()
{
return new SchoolIn.Models.CustomerList()
{
new SchoolIn.Models.Customer { Id = 1, Name = "Patrick", Address = "Geuzenstraat 29", Place = "Amsterdam" },
new SchoolIn.Models.Customer{ Id = 2, Name = "Fred", Address = "Flink 9a", Place = "Rotterdam" },
new SchoolIn.Models.Customer { Id = 3, Name = "Sjonnie", Address = "Paternatenplaats 44", Place = "Enkhuizen" },
new SchoolIn.Models.Customer { Id = 4, Name = "Henk", Address = "Wakerdijk 74", Place = "Utrecht" },
new SchoolIn.Models.Customer { Id = 5, Name = "Klaas", Address = "Paternatenplaats 44", Place = "Plaantan" }
};
}
private SchoolIn.Models.CustomerList CreateCustomerList()
{
return new SchoolIn.Models.CustomerList()
{
SchoolInDB db = new SchoolIn.Models.SchoolInDB();
var courseprogresses = db.CourseProgresses.Include(c => c.Course).Include(c => c.Teacher);
return View(courseprogresses.ToList());
};
}
First things first the second code is invalid C#. So I suppose it doesn't event compile. You cannot use such expressions in an object initialization syntax. Please learn C# before getting into ASP.NET MVC.
The other problem is that your method is private and you are attempting to return View which is something that you do in a controller action. The view method returns an ActionResult whereas your method return type is SchoolIn.Models.CustomerList which once again is wrong.
So move this into some controller action where you would instantiate your database access context and then perform the query and return the model to the corresponding view for display:
public class HomeController: Controller
{
...
public ActionResult CreateCustomerList()
{
SchoolInDB db = new SchoolIn.Models.SchoolInDB();
var courseprogresses = db
.CourseProgresses
.Include(c => c.Course)
.Include(c => c.Teacher)
.ToList();
return View(courseprogresses);
}
}
and if you wanted to keep this into a separate method:
private List<SchoolIn.Models.CourseProgress> CreateCustomerList()
{
SchoolInDB db = new SchoolIn.Models.SchoolInDB();
return db
.CourseProgresses
.Include(c => c.Course)
.Include(c => c.Teacher)
.ToList();
}
In your first function you are returning actual list while in second function you are not returning list, instead you have returned the View with model as a list. So for it you need to return View Result viz. ActionResult.
Hope it helps

Categories

Resources