LINQ/LinqPad: same query different results - linq

So we copy and paste the exact same query from LinqPad into our EF 4.3 application, pointed at the exact same database and get a different result. In LinqPad we get 2 records returned. In our application we reaise an error "Object reference not set to an instance of an object."
var Shippings = shippingRepository.All.ToArray();
var SalesOrderHeaders = salesOrderHeaderRepository.All.ToArray();
var Customers = customerRepository.All.ToArray();
var Stores = storeRepository.All.ToArray();
var Departments = departmentRepository.All.ToArray();
var toShip = from sh in Shippings
join h in SalesOrderHeaders on sh.OrderId equals h.SalesOrderHeaderId
join c in Customers on h.CustomerId equals c.CustomerId
join st in Stores on h.StoreId equals st.StoreId
join d in Departments on h.DepartmentId equals d.DepartmentId into outer
from o in outer.DefaultIfEmpty()
select new
{
OrderId = sh.OrderId,
CustomerName = c.Name,
StoreName = st.Name,
DepartmentName = (o.Name == null) ? o.Name : "None",
DeliveryDate = h.DeliveryDateTime
};
In the application code, when we remove the outer join (to add Departments) and it's associated field the query returns the same 2 records asn in LinqPad.
Does anyone have any insight into how to fix this feature?

Click on "Add a connection" in linqpad and select datacontext from assembly like
You can choose Entity Framework datacontext or Entity Framework BDContext with POCO depending upon your scenario. click next and provide path to the assembly along with connection string and you will be good to go.

In LINQPad are you actually querying against your entity model? Take a look at this link if you aren't. I had a similar problem when starting out and didn't realize I had set up a default LINQ to SQL connection earlier and was querying against that.

Related

Linq Left Outer Join Two Tables on Two Fields

How do I left outer join two tables on two fields in linq?
I have a sql:
select a.*, b.* from courselist as a
left outer join Summary as b
on a.subject = b.Subject and a.catalog =
b.Catalogno
where a.degree_id = 1
order by a.sequenceNo
Below is my linq query, but there is error underline "join", failed in the call to "Groupjoin". I don't know how to correct that.
var searchResults = (from a in db.courselist
join b in db.Summary on
new { a.subject,a.catalog } equals
new { b.Subject, b.Catalogno } into ab
where a.degree_id == 1
orderby a.degree_sequenceNo
from b in ab.DefaultIfEmpty()
select new
{
Courselist = a,
Summary = b
}
).ToList();
Thanks.
I've checked your code again,
I found it's fault
you just need to specify join parameters name like this:
new { suject = a.subject, catalog = a.catalog } equals
new { suject = b.subject, catalog = b.Catalogno } into ab
It seems you are missing the reference, the query doesn't have an error
try to use this:
using System.Linq;
The main issue when people start using LINQ is that they keep thinking in the SQL way, they design the SQL query first and then translate it to LINQ. You need to learn how to think in the LINQ way and your LINQ query will become neater and simpler. For instance, in your LINQ you don't need joins. You should use Associations/Navigation Properties instead. Check this post for more details.
There should be a relationship between courselist and Summary, in which case, you can access Summary through courselist like this:
var searchResults = (from a in db.courselist
where a.degree_id == 1
orderby a.degree_sequenceNo
select new {
Courselist = a,
Summary = a.Summary
}).ToList();
If there is no relationship between the two, then you should reconsider your design.

Performing two Left Outer Joins in a Single LINQ to CRM query

I'm attempting to perform two left outer joins in my CRM online 2015 Update 1 instance, but I am getting an error. This is what I have currently:
var query_join8 = from a in crmContext.AccountSet
join c in crmContext.ContactSet
on a.PrimaryContactId.Id equals c.ContactId
into gr
from c_joined in gr.DefaultIfEmpty()
join c in crmContext.ContactSet
on a.Name equals c.FullName
into gr2
from c2_joined in gr2.DefaultIfEmpty()
select new
{
contact_name = c_joined.FullName,
account_name = a.Name,
other_name = c2_joined.FullName
};
When I attempt to execute it, I get this error:
An exception of type 'System.NotSupportedException' occurred in
Microsoft.Xrm.Sdk.dll but was not handled in user code
Additional information: The method 'GroupJoin' cannot follow the
method 'SelectMany' or is not supported. Try writing the query in
terms of supported methods or call the 'AsEnumerable' or 'ToList'
method before calling unsupported methods.
If I comment out the second Join, it works fine:
var query_join8 = from a in crmContext.AccountSet
join c in crmContext.ContactSet
on a.PrimaryContactId.Id equals c.ContactId
into gr
from c_joined in gr.DefaultIfEmpty()
//join c in crmContext.ContactSet
//on a.Name equals c.FullName
//into gr2
//from c2_joined in gr2.DefaultIfEmpty()
select new
{
contact_name = c_joined.FullName,
account_name = a.Name,
//other_name = c2_joined.FullName
};
Microsoft Documentation:
Defining how to perform a Left Join: http://msdn.microsoft.com/en-us/library/gg509017.aspx#LeftJoin
Blog Describing that it is supported: http://blogs.msdn.com/b/crminthefield/archive/2013/01/14/crm-2011-sdk-query-limitations-by-api.aspx
The documentation on CRM 2015 still states outer joins are not supported. (MSDN: Use LINQ to construct a query) I know there is also an example on MSDN showing a left join (Sample: Complex LINQ queries), but I doubt if under the hood this is actually transformed into a single QueryExpression. So, I guess you are hitting the limits of the capabilities of Ling for CRM.

How to retieve CRM Guid using LINQ and joins?

We are using CRM 2011. We have Contracts with Entity Reference to Product and each Product has an Entity Reference to a Subject. Given a Contract Guid, I need to retrieve the Subject Guid.
I am a beginner at LINQ but I coded:
var subject = from s in context.SubjectSet
join product in context.ProductSet
on s.Id equals product.SubjectId.Id
join contract in context.ContractSet
on product.Id equals contract.ce_ProductId.Id
where contract.Id == gContractId
select s;
foreach (var s in subject)
{
newReportableAction.ce_SupergroupRegarding =
new EntityReference(Xrm.Subject.EntityLogicalName, new Guid(s.Id.ToString()));
}
This throws an error:
AttributeFrom and AttributeTo must be either both specified or both ommited. You can not pass only one or the other. AttributeFrom: , AttributeTo: ce_ProductId
What does this error mean?
How can I get the Guid?
Update:
I tried breaking the query into parts to see where the error was being generated from so I had:
var query = from product in context.ProductSet
join contract in context.ContractSet
on product.Id equals contract.ce_ProductId.Id
This gives:
"The type of one of expressions in the join clause is incorrect. Type inference failed in the call to 'Join'"
Thank you to all who help...
I don't think you can use the .Id property right off the entity in Linq statements. Try this instead:
var query = from product in context.ProductSet
join contract in context.ContractSet
on product.ProductId equals contract.ce_ProductId.Id
Notice product.ProductId instead of product.Id.

Entity Framework returns wrong data after execution of two similar queries

I have two similar queries, the first one:
var activatedSerialNumbers = (from activation in entities.Activations
where !canceledActivationsIds.Contains(activation.Id)
where activation.CustomerId == customerId
join licenseConfiguration in entities.LicenseConfigurations
on activation.Id equals licenseConfiguration.ActivationId
where licenseConfiguration.ProductId == productId
join activatedSerialNumber in entities.ActivatedSerialNumbers
on activation.Id equals activatedSerialNumber.ActivationId
where deactivatedSams.All(dsn => dsn.ToLower() !=
activatedSerialNumber.Name.ToLower())
select new SamWithLicense
{
Name = activatedSerialNumber.Name,
Features = licenseConfiguration.LicenseFeatures
}).ToList();
The second:
var activationsForSam = (from activation in entities.Activations
where !canceledActivationsIds.Contains(activation.Id)
where activation.CustomerId == customerId
let activatedSerialNumbers = activation.ActivatedSerialNumbers
.Select(sn => sn.Name.ToLower())
where activatedSerialNumbers.Contains(loweredSn)
join licenseConfiguration in entities.LicenseConfigurations
on activation.Id equals activatedProduct.ActivationId
select new SamWithLicense
{
Name = selectedSerialNumber,
Features = licenseConfiguration.LicenseFeatures
}).ToList();
In some situations I execute them one after another and in most cases it works fine, but somethimes - not. In the result of second query Counter takes from another row:
Visual Studio - Quick watch
SQL Management Studio
I guess it's a matter of a EF cache or smth, but don't know how to fix it properly.
In your first query you are joining the Activation Id (PK) to LicenseConfigurations ActivationId (FK)
join licenseConfiguration in entities.LicenseConfigurations
on activation.Id equals licenseConfiguration.ActivationId
in your second query, it looks like you are joining on a value defined outside of the query "activatedProduct"
join licenseConfiguration in entities.LicenseConfigurations
on activation.Id equals activatedProduct.ActivationId

CRM 2011 - N:N (Many-To-Many) Linq Issue

I have two entities who are N:N - related with each other. With an example I'll show you what I mean :
I have a Session (ave_Session) and there we can put "Trainers"
(ave_trainer) on each Session
I'm tryting to get a list of al the
"Trainers" for a particular Session
They are related to each other in
N:N (relationship name : ave_ave_session_ave_trainer)
I work in VS2010 and with C# => I'm trying to get the data through LINQ
I recently just started with LINQ, so maybe you guys can help me out on this one. The following I've tried and i gave me an "AttributeFrom and AttributeTo must be either both specified or both ommited. You can not pass only one or the other. AttributeFrom: , AttributeTo: ave_trainerid"-error :
var formatteurs = (from f in ORGContext.CreateQuery<ave_trainer>()
join s in ORGContext.CreateQuery<ave_ave_session_ave_trainer>() on f.Id equals s.ave_trainerid.Value
join c in ORGContext.CreateQuery<ave_session>() on s.ave_sessionid.Value equals c.Id
where c.Id == item.Id
select f).ToList();
The item.id is the Id of the session. Thx in advance if you can help me out!
From the MSDN page:
// List the contacts in the Softball team marketing list.
System.Console.WriteLine("List all contacts in Softball Team:");
var members = from c in crm.contacts
join mlm in crm.listmembers on c.contactid equals mlm.entityid
join ml in crm.lists on mlm.listid equals ml.listid
where ml.listname == "Softball Team"
select c;
foreach (var c in members)
{
System.Console.WriteLine(c.fullname + " " + c.emailaddress1);
}
It seems a little backwards the way you have it written now (assuming I'm parsing it correctly).
What you'd normally do is put your 'starting thing' first and then go through the mapping to get to the ones you want. I don't have any CRM 2011 experience, so hopefully I didn't mess this up too much. :)
Also, I'm not a fan of single-character names, so I took the liberty of using longer names :)
var formatteurs = (
// first get the session we're interested in
from session in ORGContext.CreateQuery<ave_session>()
where session.Id == item.Id
// now get the mapping rows that are related to it
join mapping in ORGContext.CreateQuery<ave_ave_session_ave_trainer>()
on session.Id equals s.ave_sessionid.Value
// now get from the mapping rows to the actual trainers
join trainer in ORGContext.CreateQuery<ave_trainer>()
on mapping.ave_trainerid.Value equals trainer.Id
select trainer
).ToList();

Resources