My method is always returning false, why? - c#

public bool IsUser(string username)
{
bool user = false;
using (var client = new datingEntities())
{
var result = from x in client.Person
select x;
foreach (var item in result)
{
if (item.Username == username)
{
user = true;
}
}
}
return user;
}
This method am I using to get data from a SQL database that I have. It's no problem with the database connection, it's just that it always is returning false even if the parameter username is existing in the database (double checked the data in the database). I tried this method before and then it worked but it don't. I'm using entity framework against my database

This will do:
public bool IsUser(string username)
{
using (var entities = new datingEntities())
{
return entities.Person.Any(p => p.Username == username);
}
}
Now you request all user entities and loop through them to see if the user matches the queried username. You should let Entity Framework or LINQ write the queries, which you do as demonstrated above.
As for the reason your function is not working: set a breakpoint, find out if any users are found at all. We can't debug that for you.

use "ToUpper()"
if (item.Username.ToString().ToUpper() == username.ToUpper())
{
user = true;
}
[EDITED]
OR use "Equal"
item.Equals(username, StringComparison.OrdinalIgnoreCase)

I would convert both item.UserName and username values to the lowercase and compare them this way. This looks more reliable. Also, your linq query can be changed to avoid the loop as follows:
var result = from x in client.Person
where x.UserName.ToLower() == userName.ToLower()
select x;

My answer is less good than others as mentioned in the comments, but I left it here for reference purposes.
I'm not sure why it returns false but what you are trying to achieve is usually done in the following way:
public bool IsUser(string username)
{
using (var client = new datingEntities())
{
User user = client.Persons.SingleOrDefault(u => u.Username == username);
return user != null;
}
}
This way is a lot more efficient than your way because you first pull all User records from the database to then iterate through them to find the one user with the Username equal to the provided string. My way tries to get the one record with the Username equal to the provided string, if no such record exists I return false and otherwise true.

Related

How to save an Id into a variable in EntityFrameworkCore and SQLite

I am very new to the Entity Framework Core and working with SQL
I have created a table called 'User' in a database and everytime I a new user is created, a new Id is also generated since it is a primary key. I want to be able save the users Id when they login, so that if they add a new workout to the workout table, then it will be saved with their Id.
I have tried:
foreach (var field in data)
{
if (context.User.Any(user => user.Name == UserName && user.Password == PassWord))
{
int UserID = context.User.Any(user => user.Id = UserID);
}
But I still don't exactly know how the queries work
Please help me.
"Any" returns a boolean.
https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.any?view=net-6.0
So the .Any in your first statement is "technically ok", but you end up doing 2 checks to find the object (your "User")....and your second Any doesn't seem correct.
See the below:
https://www.learnentityframeworkcore.com/dbset#retrieving-an-entity
So you might want to try FirstOrDefault
(the below is a modified version that comes from the "learnentityframeworkcore" website above.
int primaryKey = 0;
using (SampleContext context = new SampleContext())
{
Author foundAuthor = context.Authors.FirstOrDefault(a => a.LastName == "Shakespeare");
if (null != foundAuthor)
{
primaryKey = foundAuthor.AuthorKey;
}
}
You can also try
SingleOrDefault
where the "Single" will throw an exception if more than 1 row is found. (Your code as-is has a pitfall of finding more than one match....maybe you have a unique-constraint on username...but it isn't shown here.
Sidenotes:
your "for" loop .. looks very dangerous. how many times are you checking for the matching userid?
keeping passwords as plain text in your database is a HORRIBLE/DANGEROUS/SECURITY-ISSUE.
Don't use .Any, use .FirstOrDefault and check for null.
If your user is not null, you may access the Id property

Search a table with a lot of columns and then group the result with EntityFramework

I have an Asp.Net MVC 5 website and I'm using Entity Framework code first to access its database. I have a Restaurants table and I want to let users search these with a lot of parameters. Here's what I have so far:
public void FilterModel(ref IQueryable<Restaurant> model)
{
if (!string.IsNullOrWhiteSpace(RestaurantName))
{
model = model.Where(r => r.Name.ToUpper().Contains(RestaurantName));
}
if (Recommended)
{
model = model.Where(r => r.SearchSponsor);
}
//...
}
Basically I look for each property and add another Where to the chain if it's not empty.
After that, I want to group the result based on some criteria. I'm doing this right now:
private static IQueryable<Restaurant> GroupResults(IQueryable<Restaurant> model)
{
var groups = model.GroupBy(r => r.Active);
var list = new List<IGrouping<bool, Restaurant>>();
foreach (var group in groups)
{
list.Add(group);
}
if (list.Count < 1)
{
SortModel(ref model);
return model;
}
IQueryable<Restaurant> joined, actives, inactives;
if (list[0].FirstOrDefault().Active)
{
actives = list[0].AsQueryable();
inactives = list.Count == 2 ? list[1].AsQueryable() : null;
}
else
{
actives = list.Count == 2 ? list[1].AsQueryable() : null;
inactives = list[0].AsQueryable();
}
if (actives != null)
{
//....
}
if (inactives != null)
{
SortModel(ref inactives);
}
if (actives == null || inactives == null)
{
return actives ?? inactives;
}
joined = actives.Union(inactives).AsQueryable();
return joined;
}
This works but it's got a lot of complications which I rather not talk about for the sake of keeping this question small.
I was wondering if this is the right and efficient way to do it. It seems kind of "dirty"! Lots of ifs and Wheres. Stored procedures, inverted indices, etc. This is my first "big" project and I want to learn from your experience to do this the "right" way.
Looking at the GroupResults Method I get a little confused about what you are doing. It seems the intention is to receive an arbitrary list of restuarants and return an ordered list of restaurants ordered by Active and some other criteria.
If thats true you may just do something like this and your job's done:
model.OrderBy(x => x.Active).ThenBy(x => Name);
If SortModel is somehow more sophisticated you may either add a comparer to the statement or stick with your current solution but change it to this:
if (model == null || !model.Any())
{
return model;
}
var active = model.Where(x=>x.Active);
var inactives = model.Where(x=>!x.Active);
// if (inactives == null) //not needed as where always return at least an empty list. Mabye check for inactive.Any()
SortModel(ref inactives); //You may also remove the ref as it's an reference anyway
joined = actives.Union(inactives).AsQueryable();
return joined;
Regarding the way you are handling your searching, I think it is simple, easy to read and understand, and it works. New team members will be able to look at that code and know immediately what it is doing and how it works. I think that is a pretty good indication that your approach is sound.

Unable to get certain fields form LDAP users

I'm unable to get certain fields from user objects such as PasswordNeverExpires. Right now I'm cycling through every property returned by over 2000 users and my conditional breakpoint never breaks once, so I know it's not returning. If I break unconditionally the number of properties returned by this code is always 1.
Our sever is Windows 2003 Server. I can get all the information I want from NetEnum commands.
I've seen others claim that they can do this and I don't see what's different about my code. When I don't provide any properties to load, it grabs about 30-37 properties. Several of these properties I need and use.
public void FetchUsers(string domainId, Sql sql)
{
var entry = new DirectoryEntry("LDAP://" + DomainControllerAddress, DomainPrefixedUsername, Password,
AuthenticationType);
var dSearch = new DirectorySearcher(entry)
{
Filter = "(&(objectClass=user)(!(objectclass=computer)))",
SearchScope = SearchScope.Subtree,
PageSize = 1000,
};
dSearch.PropertiesToLoad.Add("passwordneverexpires");
var users = dSearch.FindAll();
foreach (SearchResult ldapUser in users)
{
SaveUser(ldapUser, sql, domainId);
}
}
private void SaveUser(SearchResult ldapUser, Sql sql, string domainId)
{
if (ldapUser.Properties.PropertyNames == null) return;
foreach (string propertyName in ldapUser.Properties.PropertyNames)
{
//I'm breaking here on the condition that propertyName != 'adspath' and it never breaks
var v = ldapUser.Properties[propertyName];
}
return;
}
Few things:
The base filter you have is very inefficient. Use this instead (&(objectCategory=person)(objectClass=user)).
There's no property called passwordneverexpires. You'll need to check bit 13 in the userAccountControl mask on the user - see http://msdn.microsoft.com/en-us/library/aa772300%28v=vs.85%29.aspx for a list of values.
You never break in to your loop because you're telling the client to only request one property.
You can use a filter like: (&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=65536)) to get All users with the account configuration DONT_EXPIRE_PASSWORD.
-jim

cannot "Add or Update" Entity because Primery key cannot be changed

I am implementing an import routine, where a user pastes a specific formatted string into an input field, which in turn gets tranformated into an entity and then put into a database.
The algorithm checks if the entity already exists and either tries to update it or insert it into the database. Inserting works fine - updating fails.
//considered existing if Name and owning user match.
if (db.Captains.Any(cpt => cpt.Name == captain.Name && cpt.User.Id == UserId))
{
var captainToUpdate = db.Captains.Where(cpt => cpt.Name == captain.Name && cpt.User.Id == UserId).SingleOrDefault();
db.Entry(captainToUpdate).CurrentValues.SetValues(captain);
db.Entry(captainToUpdate).State = EntityState.Modified;
await db.SaveChangesAsync();
}
The problem at hand is, that written like this, it tries to update the primary key as well, (captain Id is 0, whereas captainToUpdate Id is already set) which results in an exception The property 'Id' is part of the object's key information and cannot be modified.
What do I need to change, so the enttiy gets updated properly. If it can be avoided I don't want to update every property by hand, because the table Captain contains 30ish columns.
What you can do is first set the Id of captain to be the same as the Id of captainToUpdate:
captain.Id = captainToUpdate.Id;
db.Entry(captainToUpdate).CurrentValues.SetValues(captain);
await db.SaveChangesAsync();
I would not use the entity Captain to transfer the data to the UI, but a DTO object that has all properties you want to copy and no more. You can copy values from any object. All matching properties will be copied, all other properties in captainToUpdate will not be affected.
Try something like this ?
var captainToUpdate = db.Captains.FirstOrDefault(cpt => cpt.Name == captain.Name && cpt.User.Id == UserId);
if(captainToUpdate != null){//Update captain Here
captainToUpdate.Update(captain);
}else{//Create captain here
db.Captains.Add(captain);
}
db.Savechanges();
I had the same issue and solved it by extension method and reflection, of course it will be better to create standalone class with some cachning for relfection, but performance wasn't critical in my task.
public static class EnitityFrameworkHelper
{
public static void SetValuesByReflection(this DbPropertyValues propertyValues, object o, IEnumerable<string> properties = null)
{
var reflProperties = o.GetType().GetProperties();
var prop = properties ?? propertyValues.PropertyNames;
foreach (var p in prop)
{
var refp = reflProperties.First(x => x.Name == p);
var v= refp.GetValue(o);
propertyValues[p] = v;
}
}
}
and here is example how to use it
var entry = ctx.Entry(accSet);
entry.CurrentValues.SetValuesByReflection(eParameters, entry.CurrentValues.PropertyNames.Except(new [] { "ID"}));
Also be careful with foreign keys in object which you want to update, probably you want to exclude them too.

Checking to see if string exists in db using linq

Here's my attempt:
public void ReadLot(LotInformation lot)
{
try
{
using (var db = new DDataContext())
{
var lotNumDb = db.LotInformation.FirstOrDefault(r => r.lot_number.Equals(r.lot_number));
if (lotNumDb.lot_number != null && lotNumDb.lot_number.Length == 0)
{
Console.WriteLine("does not exist. yay");
var lotInfo = db.LotInformation.FirstOrDefault(r => r.lot_number.Equals(lotNumber));
}
else if (lotNumDb.lot_number.ToString().Equals(lot.lot_number))
{
errorWindow.Message = LanguageResources.Resource.Lot_Exists_Already;
dialogService.ShowDialog(LanguageResources.Resource.Error, errorWindow);
}
Here what I want to do:
When the user uploads a file, I check if the deserialized string from memory is a duplicate in the database or not. If it is, pop up a dialog box saying it's a duplicate/already exists and have nothing happen afterward. If it is not a duplicate, proceed with application. Also, if the column in the table in the database is null, store the lot number there and proceed.
I noticed a few things. If the database is empty and I run the above, I get a null exception because I'm trying to find a lot number in db that is not there. How do I change the code above so that if I check in db and the column is null, then just add the number and not throw an exception when comparing. I think that might be the only problem right now.
I'm not sure what this is supposed to be doing, but you don't need it:
var lotNumDb =
db.LotInformation.FirstOrDefault(r => r.lot_number.Equals(r.lot_number));
Instead, just check for the existance of the lot_number passed to the method, and use Any to determine whether there were any matches. If it returns true, then the lot number is already in the database.
// Check for duplicates
var isDuplicate = db.LotInformation.Any(r => r.lot_number == lot.lot_number);
if (isDuplicate)
{
// Inform user that the lot_number already exists
return;
}
Console.WriteLine("does not exist. yay");
// Store the lot_number in the database
bool lotNumDbExists = db.LotInformation(r => r.lot_number.Equals(r.lot_number)).Any;
or .exists
This should return either a true or false of if it exists.

Categories