Where not null using Linq - asp.net-mvc

I have a mySQL database with a Website field that is of type VarChar. Some of these fields will be null on the database.
I have an MVC application that I sending the database information to.
I am trying to set up a filter on the Index page so I can filter by certain columns. I am using the Request.QueryString to do this.
switch (Request.QueryString["FilterOptionSelect"])
{ case "CountyName":
if (!string.IsNullOrEmpty(filteredText))
{
filteredText = filteredText.ToUpper();
var modelFiltered = from n in model
where n.CountyName.ToUpper().Contains(filteredText)
select n;
return View(modelFiltered);
}
break;
case "Website":
if (!string.IsNullOrEmpty(filteredText))
{
filteredText = filteredText.ToUpper();
var modelFiltered = from n in model
where n.CountyWebsite.ToUpper().Contains(filteredText)
select n;
return View(modelFiltered);
}
break;
}
The only problem I have is on the Website case. It gives me a Object reference not set to an instance of an object. on the WHERE CLAUSE of the Website case. When I debug, my model is not null (it has 130+ items inside...some with website info and some without website info).
I have already tried using the Lambda method (which had the same problem). I have also tried using where n.CountyWebsite.ToUpper().Contains(filteredText) && n.CountyWebsite != null which did not work either.

You were on the right track with your second attempt, but you need to switch the order of those statements.
where n.CountyWebsite != null && n.CountyWebsite.Contains(filteredText)
Just like all the other && operators, you don't want to evaulate any websites that are null, so do that operation first.
Also, .Contains in EF automatically is case-insensitive, so you don't need the ToUpper().

Try this, I think this will solve.
!String.IsNullOrEmpty(n.CountyWebsite) && n.CountyWebsite.Contains(filteredText)

Related

Efficient way to get a huge number of records sorted via Linq. Also some help regarding editing an existing DB entry

The fist part of my question is
suppose I have a poco class
public class shop{
public virtual string fruitName {get;set;}
public virtual double numberOfFruitsLeftToConsume {get;set;}
public virtual double numberOfFruitsLeftForStorage {get;set;}
public virtual List<Locations> shopLocations {get;set;}
}
I add new fruits in the db by creating a new object of shop and then add it via my context then save it.
Now to retrieve the data
will it be more efficient for me to first filter by fruit name get a List then in that collection should I run my query to sort by the number of fruits to consume , or should I just put it all into one query. Supposing that the site has more than 1000 hits/sec and a massive DB, which method will be efficient.
List<shop> sh = context.shopDB.Where(p => p.fruitName == "mango" &&
p.fruitName == "apple").ToList();
List<shop> sh = sh.Where(f => f.numberOfFruitsLeftToConsume >= 100 &&
f.numberOfFruitsLeftForStorage <= 100).ToList();
The example has no meaning , I just wanted to show the type of query I am using.
The second part of my question is, when I initialize the class shop I do not initialize the List within it. Later on when I try to add it it does not get saved, the shop is connected to the user.
ApplicationUser user = await usemanager.FindByEmailAsync("email");
if(user.shops.shopLocations == null){
user.shops.shopLocation = new List<Location>();
uset.shops.shopLocation.Add(someLocation);
await context.shopDB.SaveChangesAsync();
}
////already tried
//List<Location> loc = new List<Location>();
//loc.Add(someLocation);
//user.shops.shopLocation = loc;
//await context.shopDB.SaveChangesAsync();
I tried both the methods in a try catch block and no exception is thrown.
If you need any more details or if something is not clear to you please ask.
Thank you.
If I add Location and LocationId properties to shop, and then save, I can only view the LocationId , but the Location property still remains null.
To clear any question , If I save a location Individually it saves. So I don't think I'm providing wrong data.
Now to retrieve the data will it be more efficient for me to first filter by fruit name get a List then in that collection should I run my query to sort by the number of fruits to consume , or should I just put it all into one query. Supposing that the site has more than 1000 hits/sec and a massive DB, which method will be efficient.
You are the only one who can answer that question by measuring the query performance. Only as a general rule I can say that putting all into one query and let the database do the most of the job (eventually tuning it by creating appropriate indexes) is usually preferable.
What about the second part of the question (which basically is a different question), this block
if (user.shops.shopLocations == null)
{
user.shops.shopLocation = new List<Location>();
user.shops.shopLocation.Add(someLocation);
await context.shopDB.SaveChangesAsync();
}
looks suspicious. Your shopLocations member is declared as virtual, which means it's intended to use lazy loading, hence most probably will never be null. And even if it is null, you need to keep only the new part inside the if and do the rest outside, like this
if (user.shops.shopLocations == null)
user.shops.shopLocation = new List<Location>();
user.shops.shopLocation.Add(someLocation);
await context.shopDB.SaveChangesAsync();
1st Question
Because you are calling .ToList() at the end of your queries it will have to fetch all the rows from the db each time, so it will be much faster to do all your filtering in one LINQ .Where() call like this:
List<shop> sh = context.shopDB.Where(p => p.fruitName == "mango" && p.fruitName == "apple" && f.numberOfFruitsLeftToConsume >= 100 && f.numberOfFruitsLeftForStorage <= 100).ToList();
but if you don't call .ToList() at the end of first Linq query, spliting your query into two calls will be tottally fine and will yield the same performance as the previous approach like this:
var sh = context.shopDB.Where(p => p.fruitName == "mango" &&
p.fruitName == "apple");
List<shop> shList = sh.Where(f => f.numberOfFruitsLeftToConsume >= 100 &&
f.numberOfFruitsLeftForStorage <= 100).ToList();
2nd Question
when you initialize the Location for the shop, you must set the shopId property and then it should work, if not the problem might be with your database relationships.

How can I improve this query in Entity framework 6.0?

Can someone please suggest me what wrong with this query? How can I improve the performance and decrease the time taken to execute it?
IQueryable<Mapper> query = null;
query = (from c in entities.Users
where c.UserEmailAddress == emailAddress
&& c.UserPassword == password
&& c.IsAccountVerified == true
select new Mapper()
{
UserId= c.UserID,
Name = c.UserName
});
custObj = query.ToList<Mapper>().FirstOrDefault();
I am using EF profiler it alerts me following warning:-
Query on unindexed column
Column Type mismatch
More than one session per request
FYI:-
EmailAddress - varchar(50) - Non ClusteredIndex
Password - varchar(max) - No Index
IsAccountVerified - bool - No Index
Even in local, I notice its taking 2-4 seconds to execute?
Apart from it, is there can someone suggest imp guidelines to fine tune the queries in EF.
I am using EF6.0
I think the problem is that you're using unnecessary complex query as EmailAddress is probably unique. Now you are checking three conditions to select your record, but using only email address should be fairly enough. I would rather select user basing on EmailAddress (and maybe IsAccountVerified) and later checked password hash in code.
The code would be something like this (I haven't checked it):
var user = entities.Users.FirstOrDefault(u => u.EmailAddress == emailAddress)
Mapper custObj = null;
if(user != null && user.IsAccountVerified && user.Password == password)
custObj = new Mapper
{
UserId = user.UserID,
Name = user.UserName
};
Now you are not making a query on non indexed column, and results will be the same.
I checked simillar case on MS SQL database. Select based on one condition using indexed column boosted the query nicely (0ms instead of 13ms in my case).

loop through model in mvc razor code behind

I am working on MVC4 App, and I am stuck at one point, I tried using google to help me, but without success. This might be more simple then I think, but coming from web forms and shifting to mvc is "painful" sometime.
I am trying to loop through the model I have and get the values stored in that model. I tried few approaches but I am getting an error everytime. This is what I have:
var modelAgentFilter = from s in _aa.Agents
where s.COUNTER == Convert.ToInt32(AgentID)
select s;
if (modelAgentFilter != null)
{
ViewBag.FirstName = // Get FirstName object here
}
Thanks in advance for your comments.
Laziale
EDIT:
I did include for loop like this:
if (modelAgentFilter != null)
{
foreach (var property in modelAgentFilter)
{
string test = property.ADDRESS;
}
}
But when the compiler will reach the foreach step I am getting this error: "LINQ to Entities does not recognize the method 'Int32 ToInt32(System.Object)' method, and this method cannot be translated into a store expression."
I can get to the properties of the var model using that foreach look but as soon as the compiler will try to loop the model that error pops up.
Thanks again
LINQ to Entities does not recognize any methods. You can't use even ToString() in LINQ expression. You need first convert your value and than add it in LINQ.
In your example you need to do something like following:
var _agentID = int.Parse(AgentID);
var modelAgentFilter = from s in _aa.Agents
where s.COUNTER == _agentID
select s;

Invalidate or clear certain entity types from breeze.js cache

Given a fairly standard scenario in an application, of having a list of entities that can be added/edited/deleted etc. When I first load the page, I query the entites with breeze. All good. If I edit an entity, breeze sees this and the entity is saved AND updated in the cache, so when I return to the page with the list, the item shows any relevant changes. If I delete an entity, breeze will again save that change AND update it's cache so the entity no longer appears when I return to the list page and requery the data (locally from the cache I should point out).
However, if I add a new entity, it does not appear on the list page (assuming it satisfies the requirements of the query). I'm guessing that breeze is caching the results of a query specific to that query, rather than actually querying the cache (does that make sense)?
Assuming that is the case, is there a way of telling breeze to remove or invalidate cache items relating to a specific entity type, as opposed to clearing the cache completely? I can always avoid querying the cache and go directly to the server, but that seems a waste when I know breeze has the newly created entity in the cache, it just isn't showing it to me.
I use a single method for a lot of my queries, so it may just be the way I'm handling the local querying in that method, therefore I have included it below, in case that is the cause.
var defaultQuery = function (observable, resourceName, orderby, where, expand, forceRemote, localEntityName, localCountThreshold, page, count) {
var query = EntityQuery.from(resourceName);
if (orderby) {
query = query.orderBy(orderby);
if (page) {
query = query.skip(pageSize * (page()));
query = query.take(pageSize);
query = query.inlineCount();
}
}
if (where)
query = query.where(where);
if (expand)
query = query.expand(expand);
if (!forceRemote) {
if (localEntityName) {
query = query.toType(localEntityName);
}
var localResult = manager.executeQueryLocally(query);
if (localCountThreshold) {
if (localResult.length > localCountThreshold) {
observable(localResult);
return Q.resolve();
}
} else {
if (localResult.length > 0) {
observable(localResult);
return Q.resolve();
}
}
}
return query.using(manager)
.execute()
.then(function (data) {
if (observable) {
observable(data.results);
}
if (count) {
count(data.inlineCount);
}
var logMsg = 'Retrieved ' + resourceName + ' from remote data source with order by {' + orderby + '}, where clause {' + where + '} and expand properties {' + expand + '}';
if (page)
logMsg += ' for page {' + page() + '} with total record count {' + count() + '}';
log(logMsg, data, true);
})
.fail(queryFailed);
};
Usually in questions like this, I have just misunderstood some aspect of how breeze works, so if anyone can correct me, I'd be very appreciative.
Thanks!
Update
I have included the flow of actions step by step to show in more detail what I meant.
Execute Query for all objects
Query is executed locally first, returns nothing as no cache data exists.
Query is then executed against the database - returns [A,B,C]
Edit A - rename to AA - call saveChanges()
Execute same query for all objects
Query is executed locally first, returns [AA,B,C]
Query skips executing against database as results have been found from cache.
Delete B (setDeleted()) - call saveChanges()
Execute same query for all objects
Query is executed locally first, returns [AA,C]
Query skips executing against database as results have been found from cache.
Create new entity - set name to D - call saveChanges()
Execute same query for all objects
Query is executed locally first, returns [AA,C] (does not include new D object!)
The point I'm trying to discover is that local queries return changes saved for edits and deletes, but not for add operations. I could remove entities from the cache by using setDetached as Jay suggested, but I would need to do that for all entities of a specific type one-by-one. That could be a big process.
Update again
It appears the behaviour I saw was the result of some mistake by myself. Having double and triple checked everything as a result of Jay's assertion that the results should be there (see below), the 'added' objects are now appearing, but I honestly can't explain what I did to prevent them in the first place.
Just to be clear, Breeze updates the cache when you edit an entity, it does NOT save that entity until you call EntityManager.saveChanges(). So until you call "saveChanges" the cache and your database will be in different states.
What you might be seeing is the result of the idea that when you requery an entity that has already been changed in the EntityManager, the action of merging the server side data with the client side cache is controlled by the EntityQuery.queryOptions.mergeStrategy. By default, an EntityQuery has a MergeStrategy of PreserveChanges which means that a server side result will NOT overwrite any "modified" records in the cache.
Per the later part of your post, you can remove any entity from the local cache simply by calling the entity's "entityAspect.setDetached" method.

Cannot insert duplicate key

I am getting this error ...
Violation of PRIMARY KEY constraint 'PK_Members'. Cannot insert duplicate key in object 'dbo.Members'.
The statement has been terminated.
When I try to use the Membership and Role Providers in ASP.NET MVC. It happens when calling the GetUser method from inside the RoleProvider.
var member = System.Web.Security.Membership.GetUser(email) as Models.Member;
//var member = (
// from m in DataContext.Members
// where m.Email == email
// select m).Single();
var role = (
from r in DataContext.Roles
where r.Name == roleName
select r).Single();
member.Groups.Add(new Models.Group(role));
DataContext.SubmitChanges();
It looks like the problem is in the code
member.Groups.Add(new Models.Group(role));
Based on the error message returned by the sql, Read operation like GetUser won't throw this type of error.
I suspect it's because you are adding a group that exists already.
Maybe you should check for the existance of the role before trying to add it.
Hope this helps.
A good way to debug this is to use SQL profiler to determine what SQL code is being run against the database.
I would suspect you are trying to save a record somewhere that has the same primary key already in the database.
SQL Profiler = http://msdn.microsoft.com/en-us/library/ms181091.aspx
Are you sure you are not trying to enter a number into the PRIMARY KEY field that is already there? If it is auto_increment, just enter 0 and it will make the value of that field, the last number+1
Hope this helps :)
If the exception is an SqlException you might get its error number for duplicate records which is 2627. You might catch the exception and verify it and display and manage any error accordingly. I Hope this helps.
catch (SqlException ex)
{
if (ex.Number == 2627)
{
MessageBox.Show("This record exists: "+ex.Message, "Error");
}
else
{
MessageBox.Show(ex.Message, "Error")
}
}
I am a newbie at this but I am going to give this a try, sorry if it doesn't work for you.
I think that instead of using,
member.Groups.Add(new Models.Group(role));
You should use the following (if you are updating the database):
member.Groups.Entry(new Models.Group(role));
And if the above code doesn't work, try this (if you are adding to the database):
// First, search for the particular obj you want to insert
var checkModels = member.Groups.Find(new Models.Groups(roles));
// If the obj doesn't already exist, add it to the database
if(checkModels == null){
member.Groups.Add(new Models.Group(role));
}
// If the obj does exist already, then update it
else{
member.Groups.Entry(new Models.Group(role)).State = EntityState.Modified;
}

Resources