Multiple searching in Asp.net (entity framework) with multiple search boxes - asp.net-mvc

ImageI'm having a problem to develop a form that can be search by multiple search boxes.....when i'm trying to search name and email together ActionResult...compiler says both linq queries cannot be applied with && operator..i don.t know why...
[HttpPost]
public ActionResult Login(string search,string search2)
{
var obj = db.Emps.Where(x => x.Employee_name.StartsWith(search)) && db.Emps.Where(x=>x.Employee_email.StartsWith(search2));
return View(obj);
}

You need to use both conditions inside single Where
[HttpPost]
public ActionResult Login(string search,string search2)
{
var obj = db.Emps.Where(x => x.Employee_name.StartsWith(search) && x.Employee_email.StartsWith(search2));
return View(obj);
}

If you look at your current code, the first part db.Emps.Where(x => x.Employee_name.StartsWith(search)) is going to return a collection, IQueryable<Emp>
and the second part of the expression will also return the same type, IQueryable<Emp>.
So your code is basically trying to execute/compile the expression IQueryable<Emp> && IQueryable<Emp> and since it is not valid, the compiler is telling you that it is not valid.
Ideally, you should have both of your WHERE condition predicates inside the same Where method.
var obj = db.Emps.Where(x => x.Employee_name.StartsWith(search)
&& x.Employee_email.StartsWith(search2));
Keep in mind that, the variable obj is still of type IQueryable<Emp>. If you want to execute your LINQ query, you may call the ToList() method.
List<Emp> = db.Emps.Where(x => x.Employee_name.StartsWith(search)
&& x.Employee_email.StartsWith(search2)).ToList();
If you make the above change, make sure your view is strongly typed to List<Emp> instead of IQueryable

Related

Model does not contain a definition error

I am having an issue in my project and wonder if some can pinpoint me to where i may have gone wrong. so basically in my project i have got an ActionResult method like so:
public ActionResult PartNumberManufacturer(string id)
{
var partNumber = _Context.PartNumberTable.FirstOrDefault(x => x.partNumberId == id);
return PartialView("PartNumberView", partNumber);
}
Then this is my view
#if (Model != null && !string.IsNullOrEmpty(Model.PartNumberManufacturer))
{
#if (Model.PartNumberManufacturer == "Fr")
{
<div>
<p> This product is developed in france </p>
#if (#Model.PartNumberManufacturer == "Ger")
{
<p> This Product is developed in Germany </p>
}
well the above code works fine. but the thing is that if you look back into my ActionResult controller method , i am using :
var partNumber = Context.PartNumberTable.FirstOrDefault(x => x.partNumberId == id);
FirstOrDefault of-course will only return the first found part number in the database.
This isnot what i am looking for i don't want it only to return the first found record , i want it to return all the records that match by the search query in the database. So in order to do and after a few research online i found that i had to return the results into a list and this made me amend my ActionResult method to like this:
public ActionResult PartNumberManufacturer(string id)
{
var _methodOfRepair = Context.PartNumberTable.Where(x => x.PartNumberId == id); // changed thisline
return PartialView("PartNumberView", partNumber);
}
so yeah i get the error message saying that:
{"'System.Data.Entity.Infrastructure.DbQuery' does not contain a
definition for 'PartNumberManufacturer'"}
i made those changes. what am i doing wrong here? or is there a different approach i can be recommended to in order to achieve this?
thank you for your time.
First recommendation, read about implementing the repository pattern.
Second, if you are sending a collection of objects to your View then your View need to be expecting that data type. Change the Model data type that your View is expecting.
Inside your View, you should iterate over every element and render it.

Selecting only part of the DbSet in Read method of Kendo grid

I'm trying to use a Kendo UI grid in MVC and remote data. I want to only grab and display data from the DbSet, onload, where one of the fields, "Status", equals '1'. I thought this should be able to be accomplished in the controller:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Read([DataSourceRequest] DataSourceRequest request)
{
using (var db = new MyData(false))
{
var data = db.Training.Where(d => d.Status == '1').Select(d => new Training {
Id = d.Id,
Name = d.Name,
Status = d.Status
}).ToDataSourceResult(request);
return Json(data, JsonRequestBehavior.AllowGet);
}
}
The above code gives me the error that "The entity or complex type 'Training' cannot be constructed in a LINQ to Entities query". Any suggestions on how to rewrite the Linq statement so it'll work, or maybe a way to do it within the grid to suppress any that do not have a Status of '1'?
Your code is trying to project to a mapped entity which is not allowed. Additionally it's redundant to do that as you already have your entities. Remember that .Select() is for mapping one type to another but the .Where() method is already returning a list of your entities (Training).
Remove the .Select() and the query should work:
var data = db.Training.Where(d => d.Status == '1').ToDataSourceResult(request);

How to improve my Entity Framework , to join several database queries into single query

I have the following ActionFilter class, to implement my custom authorization system:-
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CheckUserPermissionsAttribute : ActionFilterAttribute
{
Repository repository = new Repository();
public string Model { get; set; }
public string Action { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string ADusername = filterContext.HttpContext.User.Identity.Name.Substring(filterContext.HttpContext.User.Identity.Name.IndexOf("\\") + 1);
if (!repository.can(ADusername,Model,Action))
{
filterContext.Result = new HttpUnauthorizedResult("You cannot access this page");
}
base.OnActionExecuting(filterContext);
}
}
The above class will call the following repository method:-
public bool can(string user, string Model, string Action)
{
bool result;
bool result2;
int size =tms.PermisionLevels.Where(a5 => a5.Name == Action).SingleOrDefault().PermisionSize;
var securityrole = tms.SecurityroleTypePermisions.Where(a => a.PermisionLevel.PermisionSize >= size && a.TechnologyType.Name == Model).Select(a => a.SecurityRole).Include(w=>w.Groups).Include(w2=>w2.SecurityRoleUsers).ToList();
foreach (var item in securityrole)
{
result = item.SecurityRoleUsers.Any(a => a.UserName.ToLower() == user.ToLower());
var no = item.Groups.Select(a=>a.TMSUserGroups.Where(a2=>a2.UserName.ToLower() == user.ToLower()));
result2 = no.Count() == 1;
if (result || result2) {
return true;
}}
return false;
}
But inside my repository method , I am doing the following:-
Query the database and include all the Groups & SecurityRoleUsers when executing the .tolist()
Then filter the returned records insdie the server, based on the foreach loop.
But this will cause the following drawbacks:-
If I have many Groups and SecurityRoleUsers, then I will be getting them all from the DB, and then filter the result on the server.
And since this code will be executed whenever an action method is called, as it Is a security attribute at the begging of the controller class. So this might not be very efficient.
So my question is whether I can join all the queries inside the repository method to be single query , and do all the work on the Database and just return true or false to the server ?
The associated tables looks as follow:-
Ideally remove this foreach.
Try riding with Linq to Sql.
You should be more comfortable because it resembles SQL.
This link has several examples.
http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
Att
Julio Spader
wessolucoes.com.br
Use linq.
Ideally you should only have one line of code after you got the size value. e.g.
int size =tms.PermisionLevels.Where(a5 => a5.Name == Action).SingleOrDefault().PermisionSize;
var result = //One line of code to determine user authenticity
return result;
I think you should design you database in the way that join queries are easy to do. So you don't have to perform more than one select.
Try code-first EF, which links tables very easily.
You need to take care with Lazy Loading. If not used correctly, it will make a query to the database each object segmentation, especially in your foreach. With that already has a good improvement.
Take a look at this article. I think it will help you too.
http://www.sql-server-performance.com/2012/entity-framework-performance-optimization/
Att
Julio Spader
wessolucoes.com.br

cshtml runtime error: Only parameterless constructors and initializers are supported in LINQ to Entities

Want to use objects of a public class in cshtml, but got a runtime error: Only parameterless constructors and initializers are supported in LINQ to Entities. What is wrong with the following statement? Thanks for any help!
#foreach (var obj in ViewData["IncompleteList"] as IEnumerable<Games.TeamAction>)
The controller fills the ViewBag, like
IEnumerable<TeamAction> incomplete = dbIncAct.IncompleteActivity.Where(a => a.activityID == id)
.Select(s => new TeamAction(s.teamID, s.name, id, s.type));
ViewBag.IncompleteList = incomplete;
The class TeamAction (part of the namespace Games) is quite simple:
public class TeamAction
{
public TeamAction()
{
}
....
public int teamID {get; set;}
public string teamName { get; set; }
public int activityID { get; set; }
public int actionType { get; set; }
}
The answer is in the error message, once you figure out how to interpret it.
You are creating an IEnumerable via LINQ to Entities (the Entity Framework LINQ provider) like so:
IEnumerable<TeamAction> incomplete = dbIncAct.IncompleteActivity
.Where(a => a.activityID == id)
.Select(s => new TeamAction(s.teamID, s.name, id, s.type));
Note that your Select call includes a lambda expression that calls the TeamAction constructor that takes 4 parameters. As soon as you ask for the first element in the IEnumerable, LINQ tries to execute your query. At that point, it parses your lambda expression and tries to translate it into an Entity Framework query that it can run. But, as the exception message says:
Only parameterless constructors and initializers are supported
You cannot include the parameterized constructor in your LINQ query because LINQ to Entities doesn't know how to execute it. To fix the problem you have a few options.
Option One: IQueryable -> IEnumerable
The easiest way around this is to make sure the EF LINQ provider never sees the offending lambda, by forcing your IQueryable into an IEnumerable before it gets there. dbIncAct.ImcompleteActivity is probably a DbSet<>, and DbSet<>.Where returns an IQueryable that is still dependent on LINQ 2 Entities. To break that dependency, you can do:
IEnumerable<TeamAction> incomplete = dbIncAct.IncompleteActivity
.Where(a => a.activityID == id)
.AsEnumerable()
.Select(s => new TeamAction(s.teamID, s.name, id, s.type));
That will force your EF query to run up through the Where part and return an enumerable collection of IncompleteActivity entities. That thing (some internally-defined List-like object) is then used to call Select, completely apart from EF.
The downside here is that you're forcing the EF query, which probably hits a database, to happen immediately. If you don't want that, your only choice is to eliminate the parameterized constructor, using one of the other two options.
Option Two: Object Initializers
Depending on what that constructor did, you may or may not be able to easily fix it. If your constructor is just there to set properties on your newly created object, you're in luck. C# introduced the new object initializer syntax to go along with LINQ and lambdas for precisely this reason:
IEnumerable<TeamAction> incomplete = dbIncAct.IncompleteActivity
.Where(a => a.activityID == id)
.Select(s => new TeamAction
{
TeamId = s.teamID,
Name = s.name,
Id = id,
Type = s.type
});
Option Three: Refactor
If your constructor does any actual work, then you'll need to do some refactoring. Try to move as much logic into your default TeamAction() constructor as you can. You can also put some of the logic into the property setters, though you should try to minimize that as much as you can.
If your object really does require some complex initialization, the typical pattern to have an initialization method that gets called early in the life cycle, e.g:
var x = new X { ... };
x.InitializeMe();
You could do this, for example, inside your #for loop, or as a separate step immediately after you create your query.
Change it to object initialization instead:
IEnumerable<TeamAction> incomplete = dbIncAct.IncompleteActivity.Where(a => a.activityID == id)
.Select(s => new TeamAction { teamID = s.teamID, teamName = s.name, activityID = s.id, actionType = s.type });

ASP.NET MVC, LINQ and ModelBinders

Is there a pre-built ModelBinder I can use with LINQ to get an object from a DataContext and update it on a HTTP post?
For example, currently I have this block of code:
[AcceptVerbs (HttpVerbs.Post)]
public ActionResult Edit (Project project)
{
var projectService = Factory.GetService<IProjectService> ();
project = projectService.GetProject (project.ProjectId);
UpdateModel<Project> (project);
if (!ModelState.IsValid)
return View (project);
project = projectService.SaveProject (project);
return RedirectToAction ("Details", new { id = project.ProjectId });
}
(IProjectService wraps up calls to a LINQ data context)
In order to actually perform the update to the database via the LINQ data context, I need to get the project instance again and then update that instance.
Any attempt to simply save the project instance without first getting it from the data context results in nothing being written back to the database - I'm assuming because the LINQ data context knows nothing of the object it doesn't do anything with it.
Using the Attach method on the Projects table class doesn't work either btw, it throws an exception.
You should look at the implementation in Mike Hadlow's (new BSD) SutekiShop.
In there you will find a DataBindAttribute and BindUsingAttribute which, if I understand correctly, do exactly what you want to do. Notice how the DataBindAttribute.Fetch property is used to rebind the incoming data, or not, (from an HttpPost) to a LINQ entity.
I followed this pattern for one of my projects using ASP.NET MVC and LINQ-To-SQL. It works beautifully.
Here's the source: http://www.google.com/codesearch?hl=en&lr=&q=DataBind+package%3Ahttp%3A%2F%2Fsutekishop.googlecode.com&sbtn=Search
I think the project you pass in to the method is the one you want to perform UpdateModel with isn't it?
Otherwise you are trying to update with pre-existing values not new ones.
Just a thought,
Dan
Code cut out below
[AcceptVerbs (HttpVerbs.Post)]
public ActionResult Edit (Project project)
UpdateModel<Project> (project);
if (!ModelState.IsValid)
return View (project);
var projectService = Factory.GetService<IProjectService> ();
project = projectService.SaveProject (project);
return RedirectToAction ("Details", new { id = project.ProjectId });
}
You need to retrieve the original project as you do then to update it with the properties that have changed in project to update then to submit the update request.
EDIT
Try this code I found:
public static void CloneProperties(this object origin, ref object destination)
{
if (destination == null) throw new ArgumentNullException("destination", "Destination object must first be instantiated.");
foreach (var destinationProperty in destination.GetType().GetProperties())
{
if (origin != null && destinationProperty.CanWrite)
{
origin.GetType().GetProperties().Where(x => x.CanRead && (x.Name == destinationProperty.Name && x.PropertyType == destinationProperty.PropertyType)) .ToList() .ForEach(x => destinationProperty.SetValue(destination, x.GetValue(origin, null), null));
}
}
}

Resources