MSCRM 2011 EntitCollection and LINQ empty resultset - linq

I have an EntityCollection ec in C# which has been populated with all Accounts.
Now I want another List or EntityCollection from ec which has all the accounts with status active.
I am using Linq for the same.
But both form of LINQ returns a an empty result while ec has 354 number of records
var activeCRMEC = (from cl in ec.Entities
where cl.Attributes["statecode"].ToString()=="0"
select cl);
OR
var activeCRMEC = ec.Entities.Where(x => x.Attributes["statecode"].ToString() == "0");
Each time the resultset is empty and I am unable to iterate over it. And 300 or so accounts are active, I have checked.
Same thing happens when I use some other attribute such as name etc.
Please be kind enough to point out my mistake.

You can Generate Early Bound Classes to write Linq Queries.
or Else
You can Write Linq Queries Using Late Bound Using OrganizationServiceContext Class.
For Your Reference:
OrganizationServiceContext OrgServiceCOntext = new OrganizationServiceContext(service);
var RetrieveAll = OrgServiceCOntext.CreateQuery("account").
ToList().Where(w => (w.GetAttributeValue<OptionSetValue>("statecode").Value ==0)).Select(s=>s);

I'll give you a few hints, and then tell you what I'm guessing your issue is.
First, use early bound entities. If you've never generated them before, use the earlybound generator, you'll save yourself a lot headaches.
Second, if you can't use early bound entities, use the GetAttribute() method on the Entity class. It'll convert types for you, and handle null reference issues.
Your LINQ expressions look to be correct, so either the ec.Entities doesn't have any entities in it that match the criteria of "statecode" equaling 0, or you possibly have some differed execution occurring on your IEnumerables. Try calling ToList() on the activeCRMEC immediately after the LINQ statement to ensure that is not your issue.

The statecode is an OptionSetValue, you should cast it in this way
((OptionSetValue)cl.Attributes["statecode"]).Value == 0
or
cl.GetAttributeValue<OptionSetValue>("statecode").Value == 0
Both ways are valid and you should ask for the Value that it is an int.
Hope this can help you.

Related

MS CRM QueryExpression ConditionExpression w/ CRMBoolean type

I'm using Microsoft's CRM software (4.0) and I'm trying to build a query expression. It works fine with querying only String values, but now I need to include a field that is of type CRMBoolean. I should also mention I'm querying custom entities.
So previously, in my query I would only search by a few fields, but they were all of type String. Now I need to add another ConditionExpression for a CRMBoolean. The type of custom entity I'm searching for has a field called "Condition" - which will either have a value of "true" or "false". In CRM the attribute is defined as a bit, but I didn't think that would make a difference.
Here is my code I'm trying to use to find records that have a condition of "true":
oCondition = New ConditionExpression()
oCondition.AttributeName = "myEntity_condition"
oCondition.Operator = ConditionOperator.Like
Dim bool As New CrmBoolean
bool.Value = True
oCondition.Values = New Object() {bool}
listConditions.Add(oCondition)
I don't get an error, but nothing really happens. The number of records that is returned never changes one way or another. Has anyone done this before?
Thanks in advance!
Instead of putting a CrmBoolean object in the oCondition.Values array, just put a regular true/false boolean. I would also concur with benjynito on changing it to ConditionOperator.Equals instead of Like.
I don't know how the like operator is suppose to behave on a boolean. I wonder if its being ignored. Try ConditionOperator.Equal.

How do I handle no results returned from a LINQ query?

The following LINQ query works fine except when there are no results to return. Then an InvalidOperationException is thrown.
What is the best way to handle this? How do I test for the existance of a result and move along if there is none? I thought about a try-catch but felt there must be a more elegant solution.
In this example, I'm only expecting the Id of the first result. There may be other case where I want the entire object returned.
var drId = dcDest.drs.Where(dr => dr.ContactID == contactId)
.Select(dr => dr.Id).First();
int xId = drId;
You should use SingleOrDefault().
FirstOrDefault() could work too but really you are saying that there should only be one in the collection which makes 'SingleOrDefault()' the more proper choice (it will throw an exception if there is more than one).
If on the other hand you are expecting a sequence but need to handle the case when no elements are returned you can also use DefaultIfEmpty() to return a default value when the sequence is empty. See http://msdn.microsoft.com/en-us/library/bb355419.aspx
What behavior do you want when it is empty? An id of Zero or something else?

Updating tables with Linq expressions

Most of the examples I've found deal with Linq to entities, which is not what I need. I have a standard DataTable which I need to modify before returning to the caller. I can iterate over the normal Table.Rows collection or do something like this with the new extension methods:
foreach (var x in table.AsEnumerable()) {
if (x.Field<int>("SomeField") > SomeValue)
x.SetField<string>("OtherField", "OtherValue");
}
But I'm still manually looping through the entire row collection. Not necessarily a big deal, but I'm wondering if there's a more elegant way to accomplish this with Linq somehow, in the sense that I need to create an expression that iterates over the results of a query and performs an arbitrary action, rather than just select elements from the container being enumerated.
I think what you're wondering is if there's some sort of extension method like
stuff.ForEach(x => x.Value = "new value");
Unfortunately, there is no such thing. When I began using LINQ to SQL, I wanted the same thing. But unfortunately, you must use a for loop.

LINQ multiple where clause

I have a course table which I need to search based on keywords typed in the search box.
Here is a sample query:
SELECT * FROM Courses WHERE
Title LIKE '%word%' OR Title LIKE '%excel%' OR
Contents LIKE '%word%' OR Contents LIKE '%excel%'
How can I convert this in LINQ where LINQ would dynamically generate WHERE statements based on each keywords.
I tried to user PredicateBuilder it works fine as long as the field is VARCHAR. For the "TEXT" fields the quotes are not generated thus causing compiler to give an error message. Here is the SQL generated by PredicateBuilder
SELECT [t0].[CoursesID], [t0].[Title], [t0].[Contents], [t0].[Active],
FROM [dbo].[Courses] AS [t0]
WHERE ([t0].[Title] LIKE '%word%') OR ([t0].[Contents] LIKE %word%) OR
([t0].Title] LIKE '%excel%') OR ([t0].[Contents] LIKE %excel%)
Notice there is no single Quote for the "Contents" field which is a Text field in the database.
Is there any easy way to build WHERE statement and attach it with query? Does anyone know how I can do this without PredicateBuilder?
Thanks in advance.
Since you are working w/ LINQ I suppose you are working against a LINQ-to-SQL data context right? I don't have a spare DataContext lying around to test this, but this should give you some ideas.
I don't know if it will work against data context though, but most of these are pretty basic stuff (chaining OR operator and Contains method call) so it shouldn't cause problem when the query translates to SQL.
First I create a custom function that would build my predicate:
Func<string, Func<DataItem, bool>> buildKeywordPredicate =
keyword =>
x => x.Title.Contains(keyword)
|| x.Contents.Contains(keyword);
This is a function which takes a single string keyword and then return another function which takes a DataItem and checks it against the keyword.
Basically, if you pass in "Stack", you'll get a predicate: x => x.Title.Contains("Stack") || x.Contents.Contains("Stack").
Next, since there are many possible keywords and you need to chain it with an OR operation, I create another helper function to chain 2 predicates together with an OR
Func<Func<DataItem,bool>, Func<DataItem, bool>, Func<DataItem, bool>> buildOrPredicate =
(pred1, pred2) =>
x => pred1(x) || pred2(x);
This function takes 2 predicates and then join them up with an OR operation.
Having those 2 functions, I can then build my where predicate like this:
foreach (var word in keywords) {
filter = filter == null
? buildKeywordPredicate(word)
: buildOrPredicate(filter, buildKeywordPredicate(word));
}
The first line inside the loop basically checks if the filter is null. If it is, then we want a simple keyword filter built for us.
Else if the filter is not null, we need to chain existing filters with an OR operation, so we pass the existing filter and a new keyword filter to buildOrPredicate to do just that.
And then we can now create the WHERE part of the query:
var result = data.Where(filter);
Passing in the complicated predicate we've just built.
I don't know if this will different from using PredicateBuilder but since we are deferring query translation to the LINQ-to-SQL engine, there should not be any problems.
But as I said, I havn't tested it against a real data context, so if there's any problems you can write in the comments.
Here's the console app that I built to test: http://pastebin.com/feb8cc1e
Hope this helps!
EDIT: For a more generic and reusable version which involves properly utilizing the Expression Trees in LINQ, check out Thomas Petricek's blog post: http://tomasp.net/articles/dynamic-linq-queries.aspx
As predicate builder doesn't know the DB type of the property the Contains method is called on, I guess this might be a problem inside linq to sql. Have you tried with a normal query (not with predicate builder) and a TEXT column with Contains?

Debugging LINQ to SQL SubmitChanges()

I am having a really hard time attempting to debug LINQ to SQL and submitting changes.
I have been using http://weblogs.asp.net/scottgu/archive/2007/07/31/linq-to-sql-debug-visualizer.aspx, which works great for debugging simple queries.
I'm working in the DataContext Class for my project with the following snippet from my application:
JobMaster newJobToCreate = new JobMaster();
newJobToCreate.JobID = 9999
newJobToCreate.ProjectID = "New Project";
this.UpdateJobMaster(newJobToCreate);
this.SubmitChanges();
I will catch some very odd exceptions when I run this.SubmitChanges;
Index was outside the bounds of the array.
The stack trace goes places I cannot step into:
at System.Data.Linq.IdentityManager.StandardIdentityManager.MultiKeyManager`3.TryCreateKeyFromValues(Object[] values, MultiKey`2& k)
at System.Data.Linq.IdentityManager.StandardIdentityManager.IdentityCache`2.Find(Object[] keyValues)
at System.Data.Linq.IdentityManager.StandardIdentityManager.Find(MetaType type, Object[] keyValues)
at System.Data.Linq.CommonDataServices.GetCachedObject(MetaType type, Object[] keyValues)
at System.Data.Linq.ChangeProcessor.GetOtherItem(MetaAssociation assoc, Object instance)
at System.Data.Linq.ChangeProcessor.BuildEdgeMaps()
at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode)
at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)
at System.Data.Linq.DataContext.SubmitChanges()
at JobTrakDataContext.CreateNewJob(NewJob job, String userName) in D:\JobTrakDataContext.cs:line 1119
Does anyone have any tools or techniques they use? Am I missing something simple?
EDIT:
I've setup .net debugging using Slace's suggestion, however the .net 3.5 code is not yet available: http://referencesource.microsoft.com/netframework.aspx
EDIT2:
I've changed to InsertOnSubmit as per sirrocco's suggestion, still getting the same error.
EDIT3:
I've implemented Sam's suggestions trying to log the SQL generated and to catch the ChangeExceptoinException. These suggestions do not shed any more light, I'm never actually getting to generate SQL when my exception is being thrown.
EDIT4:
I found an answer that works for me below. Its just a theory but it has fixed my current issue.
I always found useful to know exactly what changes are being sent to the DataContext in the SubmitChanges() method.
I use the DataContext.GetChangeSet() method, it returns a ChangeSet object instance that holds 3 read-only IList's of objects which have either been added, modified, or removed.
You can place a breakpoint just before the SubmitChanges method call, and add a Watch (or Quick Watch) containing:
ctx.GetChangeSet();
Where ctx is the current instance of your DataContext, and then you'll be able to track all the changes that will be effective on the SubmitChanges call.
First, thanks everyone for the help, I finally found it.
The solution was to drop the .dbml file from the project, add a blank .dbml file and repopulate it with the tables needed for my project from the 'Server Explorer'.
I noticed a couple of things while I was doing this:
There are a few tables in the system named with two words and a space in between the words, i.e. 'Job Master'. When I was pulling that table back into the .dbml file it would create a table called 'Job_Master', it would replace the space with an underscore.
In the orginal .dbml file one of my developers had gone through the .dbml file and removed all of the underscores, thus 'Job_Master' would become 'JobMaster' in the .dbml file. In code we could then refer to the table in a more, for us, standard naming convention.
My theory is that somewhere, the translation from 'JobMaster' to 'Job Master' while was lost while doing the projection, and I kept coming up with the array out of bounds error.
It is only a theory. If someone can better explain it I would love to have a concrete answer here.
My first debugging action would be to look at the generated SQL:
JobMaster newJobToCreate = new JobMaster();
newJobToCreate.JobID = 9999
newJobToCreate.ProjectID = "New Project";
this.UpdateJobMaster(newJobToCreate);
this.Log = Console.Out; // prints the SQL to the debug console
this.SubmitChanges();
The second would be to capture the ChangeConflictException and have a look at the details of failure.
catch (ChangeConflictException e)
{
Console.WriteLine("Optimistic concurrency error.");
Console.WriteLine(e.Message);
Console.ReadLine();
foreach (ObjectChangeConflict occ in db.ChangeConflicts)
{
MetaTable metatable = db.Mapping.GetTable(occ.Object.GetType());
Customer entityInConflict = (Customer)occ.Object;
Console.WriteLine("Table name: {0}", metatable.TableName);
Console.Write("Customer ID: ");
Console.WriteLine(entityInConflict.CustomerID);
foreach (MemberChangeConflict mcc in occ.MemberConflicts)
{
object currVal = mcc.CurrentValue;
object origVal = mcc.OriginalValue;
object databaseVal = mcc.DatabaseValue;
MemberInfo mi = mcc.Member;
Console.WriteLine("Member: {0}", mi.Name);
Console.WriteLine("current value: {0}", currVal);
Console.WriteLine("original value: {0}", origVal);
Console.WriteLine("database value: {0}", databaseVal);
}
}
}
You can create a partial class for your DataContext and use the Created or what have you partial method to setup the log to the console.out wrapped in an #if DEBUG.. this will help you to see the queries executed while debugging any instance of the datacontext you are using.
I have found this useful while debugging LINQ to SQL exceptions..
partial void OnCreated()
{
#if DEBUG
this.Log = Console.Out;
#endif
}
The error you are referring to above is usually caused by associations pointing in the wrong direction. This happens very easily when manually adding associations to the designer since the association arrows in the L2S designer point backwards when compared to data modelling tools.
It would be nice if they threw a more descriptive exception, and maybe they will in a future version. (Damien / Matt...?)
This is what I did
...
var builder = new StringBuilder();
try
{
context.Log = new StringWriter(builder);
context.MY_TABLE.InsertAllOnSubmit(someData);
context.SubmitChanges();
}
finally
{
Log.InfoFormat("Some meaningful message here... ={0}", builder);
}
A simple solution could be to run a trace on your database and inspect the queries run against it - filtered ofcourse to sort out other applications etc. accessing the database.
That ofcourse only helps once you get past the exceptions...
VS 2008 has the ability to debug though the .NET framework (http://blogs.msdn.com/sburke/archive/2008/01/16/configuring-visual-studio-to-debug-net-framework-source-code.aspx)
This is probably your best bet, you can see what's happening and what all the properties are at the exact point in time
Why do you do UpdateJobMaster on a new instance ? Shouldn't it be InsertOnSubmit ?
JobMaster newJobToCreate = new JobMaster();
newJobToCreate.JobID = 9999
newJobToCreate.ProjectID = "New Project";
this.InsertOnSubmit(newJobToCreate);
this.SubmitChanges();
This almost certainly won't be everyone's root cause, but I encountered this exact same exception in my project - and found that the root cause was that an exception was being thrown during construction of an entity class. Oddly, the true exception is "lost" and instead manifests as an ArgumentOutOfRange exception originating at the iterator of the Linq statement that retrieves the object/s.
If you are receiving this error and you have introduced OnCreated or OnLoaded methods on your POCOs, try stepping through those methods.
Hrm.
Taking a WAG (Wild Ass Guess), it looks to me like LINQ - SQL is trying to find an object with an id that doesn't exist, based somehow on the creation of the JobMaster class. Are there foreign keys related to that table such that LINQ to SQL would attempt to fetch an instance of a class, which may not exist? You seem to be setting the ProjectID of the new object to a string - do you really have an id that's a string? If you're trying to set it to a new project, you'll need to create a new project and get its id.
Lastly, what does UpdateJobMaster do? Could it be doing something such that the above would apply?
We have actually stopped using the Linq to SQL designer for our large projects and this problem is one of the main reasons. We also change a lot of the default values for names, data types and relationships and every once in a while the designer would lose those changes. I never did find an exact reason, and I can't reliably reproduce it.
That, along with the other limitations caused us to drop the designer and design the classes by hand. After we got used to the patterns, it is actually easier than using the designer.
I posted a similar question earlier today here: Strange LINQ Exception (Index out of bounds).
It's a different use case - where this bug happens during a SubmitChanges(), mine happens during a simple query, but it is also an Index out of range error.
Cross posting in this question in case the combination of data in the questions helps a good Samaritan answer either :)
Check that all the "primary key" columns in your dbml actually relate to the primary keys on the database tables. I just had a situation where the designer decided to put an extra PK column in the dbml, which meant LINQ to SQL couldn't find both sides of a foreign key when saving.
I recently encountered the same issue: what I did was
Proce proces = unit.Proces.Single(u => u.ProcesTypeId == (from pt in context.ProcesTypes
where pt.Name == "Fix-O"
select pt).Single().ProcesTypeId &&
u.UnitId == UnitId);
Instead of:
Proce proces = context.Proces.Single(u => u.ProcesTypeId == (from pt in context.ProcesTypes
where pt.Name == "Fix-O"
select pt).Single().ProcesTypeId &&
u.UnitId == UnitId);
Where context was obviously the DataContext object and "unit" an instance of Unit object, a Data Class from a dbml file.
Next, I used the "proce" object to set a property in an instance of another Data Class object. Probably the LINQ engine could not check whether the property I was setting from the "proce" object, was allowed in the INSERT command that was going to have to be created by LINQ to add the other Data Class object to the database.
I had the same non speaking error.
I had a foreign key relation to a column of a table that was not the primary key of the table, but a unique column.
When I changed the unique column to be the primary key of the table the problem went away.
Hope this helps anyone!
Posted my experiences with this exception in an answer to SO# 237415
I ended up on this question when trying to debug my LINQ ChangeConflictException. In the end I realized the problem was that I manually added a property to a table in my DBML file, but I forgot to set the properties like Nullable (should have been true in my case) and Server Data Type
Hope this helps someone.
This is a long time ago, but I had the same problem and the error was because of a trigger with a select statement. Something like
CREATE TRIGGER NAME ON TABLE1 AFTER UPDATE AS SELECT table1.key from table1
inner join inserted on table1.key = inserted.key
When linq-to-sql runs the update command, it also runs a select statement to receive the auto generated values in the same query and expecting the first record set to contains the columns "asked for" but in this case the first row was the columns from the select statement in the trigger. So linq-to-sql was expecting two autogenerated columns, but it only received one column (with wrong data) and that was causing this exception.

Resources