Linq to Crm (2011) Trouble searching by username for systemuser - linq

I have a win app that is using linq to crm to query a system user by username
in Crm 2011(IFD). I have the following code snippet which shows what I am trying
to accomplish. The method executes without error, however no records are found.
The username appears as "domain\testuser" om CRM.
public static SystemUser LookUpSystemUser()
{
var username= "domain\\testuser");
var list = (from c in Context.CreateQuery<SystemUser>()
where c.DomainName.Equals(username)
select c).ToList();
return list.FirstOrDefault();
}

Recreating the application seemed to fix the problem. There are still no code differences, so still unsure what happened.

This really isn't an answer to your question, and in your particular instance it really won't matter due to there only being one SystemUser per DomainName, but it is a best practice.
When calling ToList() on your LINQ statement, it will return all entities from the SQL database that match the query. Then calling FirstOrDefault() will return the first, client side.
Instead of calling ToList() when only interested in one, call FirstOrDefault(). This will actually result in Top 1 added to the select query. This will result in less resources being consumed on the SQL server, CRM Webserver, and data being transfered between the SQL server, the CRM Webserver, and the client.

Try to run this method (or a canonical equivalent of it) and see if you get anything at all. If so, you can then tighten up the condition in Select statement.
public static SystemUser LookUpSystemUser()
{
return Context.CreateQuery<SystemUser>()
.Select(element => true)
.FirstOrDefault();
}
Remember that default(SystemUser) will produce null.
Not at the computer, haven't tested it.

Related

How does entity framework optimize linq queries

I am using Azure Mobile Web Services with an Entity Framework Database and am wondering about how to structure my linq query. I have a UserSetting and a User table, with UserSetting being a one-to-many with User. However, since I don't have referential constraints, I don't have a UserId property to query against in linq. So, I'd like to, in one operation, get the UserId and get all UserSettings belonging to the user. Also, I'm posting here because I'm having a hard time figuring out break points on a Web Service when a query is run so I can look at the SQL
So, my question is are these two queries the same thing?
return Query().Where(setting => setting.User.AccountId == currentUser.Id);
return from setting in Query()
let user = context.Users.SingleOrDefault(user => user.AccountId == currentUser.Id)
where setting.User == user
select setting;

Linq security - hide columns

I am struggling a bit on what probably is a simple matter or something I misunderstand... But anyway, using Linq entity code first, I am trying to keep some of my tables to be inaccessible from the client, without success.
Using Breeze, I have made a datacontext that holds only the dbsets I want exposed, fine.
But when I write a query using .expand(). For example, let's say I have a posts table which I want to expose, and an Owner table that I want to hide.
Using a query like:
var query = EntityQuery
.from('Posts')
.expand('Owner');
I can still see all the columns from Owner.
So the question is: in Linq, how am I supposed to secure/protect/hide the tables, and/or specific columns, that I want to hide?
After some digging, all I have found is the [JsonIgnore] attribute, which seems insufficient to me.
What is the best way to do this? I feel I am missing something probably huge here, but it's the end of the day around here...
Thanks
If you are using the Breeze's WebApi implementation then Breeze also supports ODataQueryOptions ( see here and here ).
This allows you to mark up your controller methods so as to limit how the query is interpreted. For example, to only allow filtering on your 'Posts' query and therefore exclude the ability to "expand" or "select" 'Owners' from any 'Posts' request you could do the following.
[Queryable(AllowedQueryOptions=AllowedQueryOptions.Filter| AllowedQueryOptions.Top | AllowQueryOptions.Skip)]
public IQueryable<Posts> Posts() {
....
}
Ok apparently my question was already addressed here:
Risks of using OData and IQueryable
I just found it.

Am I abusing of Linq to objects?

I think that queries with linq to objects end up very readable and nice. For example:
from person in db.Persons.ToList()
where person.MessageableBy(currentUser) ...
Where MessageableBy is a method that can't be translated into a store expression (sql)
public bool MessageableBy(Person sender)
{
// Sender is system admin
if (sender.IsSystemAdmin())
return true;
// Sender is domain admin of this person's domain
if (sender.Domain.DomainId == this.Domain.DomainId && this.Domain.HasAdmin(sender))
return true;
foreach (Group group in this.Groups)
{
if (group.MessageableBy(sender))
return true;
}
// The person is attorney of someone messageable
if (this.IsAttorney)
{
foreach (Person pupil in this.Pupils)
if (pupil.MessageableBy(sender))
return true;
}
return false;
}
The problem is that I think that this is not going to scale. I'm already noticing that with a few entries in the database, so can't imagine with a large database.
So the question is:
Should I mix linq to entities with linq to objects (ie: apply some of the "where" to the ICollection and some of the "where" to the .ToList() result of that? should I only use linq to entities, ending with a very large sentence?
.ToList() will actually execute the query and fetch all the data in that table, which is not something you'd want unless you know for sure it'll always be few records. So yes, you should do more in the where clause before doing .ToList()
I largely agree with your initial analysis. Mixing Linq to Objects and Linq to Entities is fine, but requires retrieving more data than is necessary, and therefore could lead to scaling problems down the road.
Remember to design you data model to support the critical queries. Perhaps a user could be a person, and person could have a self relationship that determines who can message who. This is just a simple thought, to inspire you to consider other ways of representing your data to allow the MessableBy method to be realized in the query itself.
In the meantime, if it isn't causing performance problems, then I would consider this issue more in terms of model design.
Although this simply paraphrases the statements made by earlier respondents, I believe it is important to enough to truly emphasize:
It is critical for DB application performance to perform as much calculation as possible, and particularly as much filtering and aggregation as possible, on the DB server prior to sending the resulting data to the client.

Execute IQueryable on DB Layer and return a new One (eraly execute)

I wnat that my DB Layer Returns a IQueryable of its DTO Objects. I use NHibernate wich has support for Linq. But the problem is, i've to close the session when my DB Layer is leaved, and so the IQueryable does not work any more.
But I also could not return a List because then the Querys will not be Executed on the SQL Server.
So is it possible that i Return a IQueryable, exceute the Expression with the Nhibernate LINQ and Return a New IQueryable??
maybe something like this:
public IQueryable<TagDTO> Tags
{
get
{
using (var session = factory.OpenSession())
{
return new ExceuteQueryable<TagDTO>(session.Query<TagDTO>());
//return session.Query<TagDTO>();
}
}
}
where ExceuteQueryable should use it's Expression Tree to execute the Query, get a List of the Results and return a new iqueryable of the List?
executing early is the same as returning a list. Without a connection to the database (session) how can you possibly execute a query on it? Do not micromanage the session like this instead use/hold a session for the whole buisiness operation and there 's no problem with closed transactions anymore.
Returning IQueryable from the DAL will lead to pain sooner than you think because the dataaccess has absolutly no context to optimise the access (eager fetching, filtering, ToList() for iterating multiple times). Also consistent caching is near impossible without context.

Performace issue using Foreach in LINQ

I am using an IList<Employee> where i get the records more then 5000 by using linq which could be better? empdetailsList has 5000
Example :
foreach(Employee emp in empdetailsList)
{
Employee employee=new Employee();
employee=Details.GetFeeDetails(emp.Emplid);
}
The above example takes a lot of time in order to iterate each empdetails where i need to get corresponding fees list.
suggest me anybody what to do?
Linq to SQL/Linq to Entities use a deferred execution pattern. As soon as you call For Each or anything else that indirectly calls GetEnumerator, that's when your query gets translated into SQL and performed against the database.
The trick is to make sure your query is completely and correctly defined before that happens. Use Where(...), and the other Linq filters to reduce as much as possible the amount of data the query will retrieve. These filters are built into a single query before the database is called.
Linq to SQL/Linq to Entities also both use Lazy Loading. This is where if you have related entities (like Sales Order --> has many Sales Order Lines --> has 1 Product), the query will not return them unless it knows it needs to. If you did something like this:
Dim orders = entities.SalesOrders
For Each o in orders
For Each ol in o.SalesOrderLines
Console.WriteLine(ol.Product.Name)
Next
Next
You will get awful performance, because at the time of calling GetEnumerator (the start of the For Each), the query engine doesn't know you need the related entities, so "saves time" by ignoring them. If you observe the database activity, you'll then see hundreds/thousands of database roundtrips as each related entity is then retrieved 1 at a time.
To avoid this problem, if you know you'll need related entities, use the Include() method in Entity Framework. If you've got it right, when you profile the database activity you should only see a single query being made, and every item being retrieved by that query should be used for something by your application.
If the call to Details.GetFeeDetails(emp.Emplid); involves another round-trip of some sort, then that's the issue. I would suggest altering your query in this case to return fee details with the original IList<Employee> query.

Resources