PartialView passing Customized List using LINQ - c#

I have 2 Databases using EF w/ MVC4. I have searched all through SO to avail. I need to return a list of Alerts to a partial view. However the Alerts should be filtered by a specific username with a specific identifier. The View is strongly typed, and I'd like to keep it like that.
I have the LINQ query returning to a List and it's the list of the usernames associated with the specific id. You can see in the second case statement where the two table lookup needs to go.I want to do this without a viewmodel class.
Here is the code:
public PartialViewResult DashboardAlerts()
{
Database.SetInitializer<AlertsContext>(null);
AlertsContext db = new AlertsContext();
Database.SetInitializer<MemberUsersContext>(null);
MemberUsersContext mdb = new MemberUsersContext();
var members = new List<MemberUsers>(mdb.MemberUsers);
var alerts = new List<Alerts>(db.Alerts);
var query = from x in alerts
join y in members
on x.username equals y.username
where y.clubID == (int)Session["ClubID"]
select new { username = y.username};
var list = query.ToList();
switch (Session["RoleName"].ToString())
{
case "GMC Admin": return PartialView(db.Alerts.ToList());
case "Club Admin": return //return db.Alerts.ToList() that has only usernames from query.ToList();
default: return PartialView(db.Alerts.Where(x => x.username == User.Identity.Name).ToList());
}
}
Bottom Line: I want to cross reference db.Alerts with only values from query list's username property.

From your question, you use want to narrow down the alerts to the ones where you have the usename in query. looks like you already have that done, just dont select the username, but the alert instead
var query = from x in alerts
join y in members
on x.username equals y.username
where y.clubID == (int)Session["ClubID"]
select x;
that will return you the alerts rather than the list of usernames.

Related

Select multiple columns with linq to sql [duplicate]

This question already has answers here:
Linq Syntax - Selecting multiple columns
(3 answers)
Closed 5 years ago.
I am trying to select multiple columns by using LinqToSql, but I am having a hard time with it. I am quite new in LinqToSql.
When I am selecting 1 column I do it like this:
string[] name = mycontext.Users.SingleorDefault(p => p.UserId == 1).UserName;
Is there anything similar for multiple columns?
I actually want to assign Name and Surname in a ListBox control
Use Anonymous Types:
var result = mycontext.Users.Where(p => p.UserId == 1)
.Select(c => new {c.UserName , c.Family ,...})
.SingleOrDefault();
You current request will query the whole user (select *).
In most cases, it is enough and you can access to each column separately :
var user = mycontext.Users.SingleorDefault(p => p.UserId == 1);
var userName = user.Username;
var password = user.Password;
// etc...
If you only need one (or several columns) but not the whole user, you can do it like this:
var userInfo = mycontext.Users.Where(p => p.UserId == 1).Select(p => new {p.UserName, p.Password}).SingleOrDefault();
var userName = userInfo.UserName;
var password = userInfo.Password;
If you prefer a collection of string in result, you can do it this way:
List<string> userInfo = mycontext.Users.Where(p => p.UserId == 1).Select(p => new List<string> { p.UserName, p.Password }).SingleOrDefault();
var username = userInfo[0];
var password = userInfo[1];
This way, the generated query will looks like Select UserName, Password From UserTable. Its usefull only if your table has a lots of columns or a heavy one (blob for example).
How it works: by calling the Where extension methods firstly, you tell .NET to not run the query immediately. It will be executed on the SingleOrDefault call. But at this moment, the query has been completed and the whole part is done in SQL.
Can't you return User object?
var user = mycontext.Users.SingleorDefault(p => p.UserId == 1)
After that you can get all properties of User without creating dynamic types

Get all usernames from database to a list in MVC 4

I have this controller:
public ActionResult NameSearch(SearchModel userSearch)
{
if (ModelState.IsValid)
{
var db = new reviewlogsEntities();
return View(db.logrecords.Where(m => m.username == userSearch.userName).ToList());
}
return RedirectToAction("index", "home");
}
My question is the user that is currently searching for logs is looking for a username once they have a username they can output a list. The problem I am having right now is what would my requirements be if they don't enter a username. What should happen is all users and their logs should come up. I could just make an if statement that says if left empty just do
return View(db.logrecords.ToList());
I feel like there is another way I could do it without having to do that. Because my thought process is, what if the search needs to be more complex. Where they might not enter a username but they could enter a date they are looking specifically for, or vise versa. I couldn't really do if statements then without it being super messy. Any help would really be appreciated!
You can add an if condition and do more filtering on the logrecords dbset as needed.
Assuming db is an object of your DbContext and db.logrecords is of type DbSet<LogRecord>
IQueryable<LogRecord> recordsDbSet = db.logrecords;
if(!String.IsNullOrEmpty(userSearch.UserName))
{
recordsDbSet = recordsDbSet.Where(m => m.username == userSearch.userName)
}
var resultList = recordsDbSet.ToList();
return View(resultList);
If you are planning to create more search fields in the future, you will want to set up your query to accommodate that without refactoring. Here's is a common approach:
var searchResults = db.logresults.AsQueryable();
//User Name
if (userSearch.username != string.empty)
searchResults = searchResults.Where(l => l.username == userSearch.username);
//From Date
if (userSearch.FromDate != DateTime.MinValue)
searchResults = searchResults.Where(l => l.CreatedDate >= userSearch.FromDate);
//To Date
if (userSearch.ToDate != DateTime.MinValue)
searchResults = searchResults.Where(l => l.CreatedDate <= userSearch.ToDate);
//Category (because logs always end up categorized)
if (userSearch.Category != LogCategories.All) //assuming enum here
searchResults = searchResults.Where(l => l.Category == userSearch.Category);
Setting up your method like this is easy to follow and extend when new search criteria are added, and the resulting query only includes the parameters entered by the user.

MVC Unable to display Linq query result to view

I'm trying to display linq results into a view but I have not been able to. The error I get is "The model item passed into the dictionary is of type 'System.Data.Entity.Infrastructure.DbQuery1[<>f__AnonymousType22[System.Double,System.String]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable"
I created my view manually and by right clicking the controller and adding a view but I'm kind of stuck here.
public ActionResult leftjoin()
{
var q = from b in db.OrderHistories
join c in db.BuyerComms on b.ITEMID equals c.ITEMID into sr
from x in sr.DefaultIfEmpty()
select new { Item = b.ITEMID, buyer = x.Buyer };
return View (q.ToList());
}
and my view:
#model IEnumerable<myapp.Models.OrderHistory>
I used linqpad to test my linq and I'm getting the right results.
Your query is returning an anonymous type as indicated by:
select new { Item = b.ITEMID, buyer = x.Buyer };
You need to instead select into a type of OrderHistory. You didn't provide that class, so I'm going to guess that it's something like:
select new OrderHistory { Item = b.ITEMID, buyer = x.Buyer };

Join tables in NHibernate without mapping

I have the following two objects:
User
class User {
public int role;
}
Role
class Role {
public int id;
public string name;
}
be note that role property inside User is int and not Role, that's our limitations.
I want to join between all the users and each of his role. In the mapping objects there is no reference as you can understand, just a simple type (int).
How do I do that join statement?
It's called a theta join:
var a = (from u in session.Query<User>()
from r in session.Query<Role>()
where u.role == r.id
select new { u.Username, Role = r.name }).ToList();
Assuming you have a Username property on the User class.
Yes, this "theta join" (as I just learned this term) is very handy and let's us not worry about putting in pointless mapping relationships.
WARNING HOWEVER IN USING THIS!!! This tripped me up a lot.
Adding to the above example...
var list = new List<int>( { 2, 3 } ); // pretend in-memory data from something.
var a =
(from u in session.Query<User>()
from x in list
from r in session.Query<Role>()
where u.role == r.id
where r.id == x.id // pretend list wants to limit to only certain roles.
select new { u.Username, Role = r.name }).ToList();
THIS WILL BOMB with some NotSupported exception.
The trick is that anything coming from NHibernate Session must come LAST. So this alteration WILL work:
var a =
(from x in list
from u in session.Query<User>()
from r in session.Query<Role>()
where u.role == r.id
where r.id == x.id // pretend list wants to limit to only certain roles.
select new { u.Username, Role = r.name }).ToList();
And and BTW, you can use join as well, however you have to make sure if you have any nullable data types, that you use the .Value if you are joining to something not-nullable.
var a =
(from x in list
from u in session.Query<User>()
join r in session.Query<Role>() on u.role equals r.id
where r.id == x.id // pretend list wants to limit to only certain roles.
select new { u.Username, Role = r.name }).ToList();
And while we're at it, let's say you have a method that has some dynamic condition. In this example the 'list' which could be a list of roles to filter by, but don't filter at all if the list is not there. Well, if you do the .ToList() then you are causing this query to execute immediately. But instead you can add a condition and then execute it later:
var a =
from u in session.Query<User>()
join r in session.Query<Role>() on u.role equals r.id
where r.id == x.id // pretend list wants to limit to only certain roles.
select new { u.Username, Role = r.name, RoleID = r.id }; // Adding the Role ID into this output.
if (list != null) // assume if the list given is null, that means no filter.
{
a = a.Where(x => list.Contains(x.RoleID));
// WARNING. Unfortunately using the "theta" format here will not work. Not sure why.
}
var b = a.ToList(); // actually execute it.
var c = a.Select(x => new { x.Username, x.Role }).ToList() // if you insist on removing that extra RoleID in the output.
One last thing.. Sometimes some simple logic will fail when executed in the select new { .. } part. I don't have an explanation. In our case the logic was just converting a DB value of a uint to an Enumerator of a model. But to get around that, I just avoided doing that conversion while reading the data but saved the value. Then in a later step, after the data was loaded, I just did the conversion in another LINQ statement.
DISCLAIMER: While I wrote many of these things all the past several weeks, I did not put this code into my compiler to verify 100%.

Linq Select Clause w/ Unknown Number of Fields

I have a linq query in which I need to be able to select an variable number of fields from a datatable. I do know all of the fields that could be included, but only two will for sure be in the datatable. I also will know which fields are included in the datatable (it will just be different depending on the user's selections). Right now I set up something like this:
var query = from item in dt.AsEnumerable()
group item by item.Field<string>("ID") into g
select new
{
ID = g.Key, //required
Status = g.Min(i => dostuff(i,"Status")), //not required
Disc = g.Min(i => dostuff(i,"Disc")), //not required
Loc = String.Join<string>(",", from i in g select i.Field<string>("Loc")) //required
};
dostuff(DataRow i,string field)
{
try
{
return i.Field<string>(field);
}
catch
{
return null;
}
}
So dostuff basically is just checking whether or not that field exists in the dataset, and then I would just need to ignore the non-existant fields when working with the query results, which would not be too difficult. However, it seems like there is probably a better way to do this, but I've had a tough time finding anything via Google about using a dynamic select clause.
You could do it with dynamic type (nb, I did not test so this might have typos.):
var query =dt.AsEnumerable().GroupBy(item => item.Field<string>("ID"))
.Select(g => {
dynamic t = new System.Dynamic.ExpandoObject();
if (g.Table.Columns.Any(c => c.ColumnName == "Status"))
t.Status = g.Field<string>("Status");
if (g.Table.Columns.Any(c => c.ColumnName == "Disc"))
t.Disc = g.Field<string>("Disc");
t.ID = g.Key;
t.Loc = String.Join<string>(",",g.Select(i => i.Field<string>("Loc")));
return t;
}

Categories