I went and got latest and made a build and the LegacySkip mode works great, but now I'm getting a null reference exception in DelegateBindExtensionsBind<t1, t2,="" t3,="" tresult="">(this Func<t1, t2,="" t3,="" tresult=""> d, T1 arg1):

System.NullReferenceException occurred Message="Object reference not set to an instance of an object." Source="Anonymously Hosted DynamicMethods Assembly" StackTrace: at lambda_method(ExecutionScope , Object[] , Tuple , ItemMaterializationContext ) at System.DelegateBindExtensions.<>cDisplayClassa`4.<bind>b9(T2 arg2, T3 arg3) in c:\Program Files\DataObjects.Net\src\Xtensive.Core\Xtensive.Core\System\DelegateBindExtensions.cs:line 46 InnerException:

None of the parameters (arg1, arg2, arg3) are null, not is the parameter d in the dele...so I'm not sure what the cause of the error is.

Any idea how to troubleshoot this issue? Or could is it something you're already aware of?

Thanks.


Updated at 11.03.2010 15:38:33

Actually that is the full stack trace I see in the debugger :)

The call stack is:

[External Code] 
>   Xtensive.Core.dll!System.DelegateBindExtensions.Bind<object[],Xtensive.Core.Tuples.Tuple,Xtensive.Storage.Linq.Materialization.ItemMaterializationContext,MyOrg.TheCompany.Data.Shared.Entities.TheCompanyCompany>.AnonymousMethod(Xtensive.Core.Tuples.Tuple arg2 = {(511031, 181, the guy, One International Pl., null, null, Boston, MA , 02110-2602, United States, +1 617-951-7237, +1 N/A, null, 150, 139, Advisor, IAT, 6, 141, GR        , Growth, False, False, null, null, null)}, Xtensive.Storage.Linq.Materialization.ItemMaterializationContext arg3 = {Xtensive.Storage.Linq.Materialization.ItemMaterializationContext}) Line 46 + 0x26 bytes   C#
    Xtensive.Storage.dll!Xtensive.Storage.Linq.Materialization.MaterializationHelper.Materialize<MyOrg.TheCompany.Data.Shared.Entities.TheCompanyCompany>.AnonymousMethod(Xtensive.Core.Tuples.Tuple tuple = {(511031, 181, guy, address., null, null, Boston, MA , 02110-2602, United States, +1 617-951-xxxx, +1 N/A, null, 150, 139, Advisor, IA, 6, 141, GR        , Growth, False, False, null, null, null)}) Line 116 + 0x41 bytes    C#
    [External Code] 
    Xtensive.Core.dll!System.EnumerableExtensions.Batch<MyOrg.TheCompany.Data.Shared.Entities.TheCompanyCompany>(System.Collections.Generic.IEnumerable<MyOrg.TheCompany.Data.Shared.Entities.TheCompanyCompany> source = {System.Linq.Enumerable.WhereSelectEnumerableIterator<Xtensive.Core.Tuples.Tuple,MyOrg.TheCompany.Data.Shared.Entities.TheCompanyCompany>}, int firstFastCount = 2, int initialBatchSize = 16, int maximalBatchSize = 1024) Line 497 + 0x138 bytes    C#
    Xtensive.Core.dll!System.EnumerableExtensions.ApplyBeforeAndAfter<MyOrg.TheCompany.Data.Shared.Entities.TheCompanyCompany>(System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<MyOrg.TheCompany.Data.Shared.Entities.TheCompanyCompany>> source = {System.EnumerableExtensions.Batch<MyOrg.TheCompany.Data.Shared.Entities.TheCompanyCompany>}, System.Action beforeAction = {Method = {Void Activate()}}, System.Action afterAction = {Method = {Void Deactivate()}}) Line 593 + 0xc bytes   C#
    [External Code] 
    Xtensive.Storage.dll!Xtensive.Storage.TransactionalExtensions.ToTransactional<System.Collections.Generic.IEnumerable<MyOrg.TheCompany.Data.Shared.Entities.TheCompanyCompany>>.MoveNext() Line 332 + 0x55 bytes C#

And the expression tree looks like:

All().Select(c => new TheCompanyCompany() {ProviderKey = c.company_id, Name = c.company_nm, PrimaryPhone = c.primary_phone, PrimaryFax = c.primary_fax, Url = c.url, CompanyType = Convert(All().Select(ct => new TheCompanyCompanyType() {ProviderKey = ct.type_id, Name = ct.type_nm, Code = ct.type_cd})).Where(ct => ((ConvertChecked(ct.ProviderKey) = c.primary_cmp_type_id) ?? False)).Select(ct => ct).FirstOrDefault(), CompanyStyle = Convert(All().Select(cst => new TheCompanyCompanyStyle() {ProviderKey = cst.style_id, Name = cst.style_nm, Code = cst.style_cd, BuysideInd = Convert(cst.buyside_ind), SellsideInd = Convert(cst.sellside_ind)})).Where(cst => ((ConvertChecked(cst.ProviderKey) = c.primary_style_id) ?? False)).Select(cst => cst).FirstOrDefault(), CompanyIndustry = Convert(All().Select(ind => new TheCompanyIndustry() {ProviderKey = ind.industry_mid_id, Name = ind.industry_mid_nm})).Where(i => ((ConvertChecked(i.ProviderKey) = c.industry_id) ?? False)).Select(i => i).FirstOrDefault(), Address = new MyAddress() {ProviderKey = c.company_id, AddressLine1 = c.primary_address_line_1, AddressLine2 = c.primary_address_line_2, AddressLine3 = c.primary_address_line_3, City = c.primary_address_city, State = c.primary_address_state_cd, Zip = c.primary_address_zip_cd, Country = c.primary_address_country_nm}}).Select(i => i).Take(100)

Updated at 13.03.2010 16:53:29

Well, you're certainly correct. It is a complex query....which is why I've wanted to try it with DO.

I found the issue via your advice and I have the query working. The good news is that the speed is 3x-4x the speed of LINQ to SQL because it produces 3 SQL queries as opposed to 1 + (n * rows) produced by LINQ to SQL. However, I'm not sure if the DO materialization should have required the null check where it does.... LINQ to SQL does not throw a null reference exception and I'm not sure LINQ to memory would do it either... Specfically, the issue is in the nested subquery for ParentCompany below.

Note that in the final clause, I've done CompanyID = c !=null ?c.company_id:0 instead of just CompanyID = c.company_id (like the other rows). This causes the query to succeed without the null reference exception...but it doesn't make sense to me why this should be necessary in the subquery....given the FirstOrDefault, I would think it would just return null.

Sorry if my question is a little abstract here.

Thanks for all the assistance.

var queryCompany = from c in Query.All<company>()
                               where
                                   !c.deleted_ind
                               select new
                               {
                                   CompanyID = c.company_id,
                                   Name = c.company_nm,
                                   Address_City = c.primary_address_city,
                                   Address_Country = c.primary_address_country_nm,
                                   Address_Line1 = c.primary_address_line_1,
                                   Address_Line2 = c.primary_address_line_2,
                                   Address_Line3 = c.primary_address_line_3,
                                   Address_State = c.primary_address_state_cd,
                                   Address_Zip = c.primary_address_zip_cd,
                                   Fax = c.primary_fax,
                                   Phone = c.primary_phone,
                                   Website = c.url,
                                   LastModifiedDate = c.last_modified_utc_dttm,
                                   CompanyType = CompanyInfoType.Institution
                               };

            var queryFund = from f in Query.All<fund>()
                            where
                                !f.deleted_ind
                            select new
                            {
                                CompanyID = f.fund_id,
                                Name = f.fund_nm,
                                Address_City = f.primary_address_city,
                                Address_Country = f.primary_address_country_nm,
                                Address_Line1 = f.primary_address_line_1,
                                Address_Line2 = f.primary_address_line_2,
                                Address_Line3 = f.primary_address_line_3,
                                Address_State = f.primary_address_state_cd,
                                Address_Zip = f.primary_address_zip_cd,
                                Fax = f.primary_fax,
                                Phone = f.primary_phone,
                                Website = f.url,
                                LastModifiedDate = f.last_modified_utc_dttm,
                                CompanyType = CompanyInfoType.Fund
                            };

            var queryUnion = queryCompany.Union(queryFund)

            var queryResult = from r in queryUnion
                              select new CompanyInfo
                              {
                                  CompanyID = r.CompanyID,
                                  Name = r.Name,
                                  Address_City = r.Address_City,
                                  Address_Country = r.Address_Country,
                                  Address_Line1 = r.Address_Line1,
                                  Address_Line2 = r.Address_Line2,
                                  Address_Line3 = r.Address_Line3,
                                  Address_State = r.Address_State,
                                  Address_Zip = r.Address_Zip,
                                  Fax = r.Fax,
                                  Phone = r.Phone,
                                  Website = r.Website,
                                  LastModifiedDate = r.LastModifiedDate,
                                  CompanyType = r.CompanyType,
                                  ParentCompany = (from c in Query.All<company>()
                                                   join cf in Query.All<company_fund>() on c.company_id equals cf.company_id
                                                   where
                                                       !c.deleted_ind
                                                       && !cf.deleted_ind
                                                       && cf.priority_rank == 1
                                                       && cf.fund_id == r.CompanyID
                                                       && r.CompanyType == CompanyInfoType.Fund
                                                   select new CompanyInfo
                                                   {
                                                       CompanyID = c != null ? c.company_id : 0
                                                       //Name = c.company_nm,
                                                       //Address_City = c.primary_address_city,
                                                       //Address_Country = c.primary_address_country_nm,
                                                       //Address_Line1 = c.primary_address_line_1,
                                                       //Address_Line2 = c.primary_address_line_2,
                                                       //Address_Line3 = c.primary_address_line_3,
                                                       //Address_State = c.primary_address_state_cd,
                                                       //Address_Zip = c.primary_address_zip_cd,
                                                       //Fax = c.primary_fax,
                                                       //Phone = c.primary_phone,
                                                       //Website = c.url,
                                                       //LastModifiedDate = c.last_modified_utc_dttm,
                                                       //CompanyType = CompanyInfoType.Institution,
                                                       //ParentCompany = null
                                                   }).FirstOrDefault()
                              };

            return queryResult;

This thread was imported from our support forum. The original discussion may contain more detailed answer. Original topic by JeffN.

asked Mar 10 '10 at 22:31

Editor's gravatar image

Editor
46156156157

Can you provide a full stack trace? It woudl be great to know who's the caller, since .Bind extension methods are widely used for currying.

(Mar 10 '10 at 22:31) Alex Yakunin Alex%20Yakunin's gravatar image

One Answer:

Clear that an expression materializing the item produced (by our LINQ translator) is either wrong, or you really get null somewhere and try to invoke a method on this object later.

E.g. if your final .Select contains code like this:

var bookTitleLengths =
  from a in Query.All<Book>()
  select a.Title.Length;

It will fail, if one of books has null Title.

Final item materialization steps are performed on the client, when this is possible. So e.g. this query will ALWAYS work on SQL Server, but won't work on IMDB, if there are null Titles (because IMDB query pipeline deals with nulls as .NET does):

var existingBookTitles =
  from a in Query.All<Book>()
  where a.Title.Length!=0 // Will work ok, because result of LEN(NULL) is NULL, so the condition 
  select a.Title;

Btw, such null handling isn't specific to DO4. All LINQ-to-SQL translators handle this nearly the same way, including L2S and EF. Trying to simulate .NET null semantics in SQL, the underlying SQL query would grow much faster than original LINQ expression; such queries have much lower chances to produce good query plans.

So it's better to simply know this (i.e. keep in mind there is SQL null semantics everywhere except expressions that can be computed on the client) and take this into account.


I can only recommend you to think where you can get nulls - e.g. by narrowing down the case you deal with.

There are several places that might lead to them, e.g. .FirstOrDefault() calls. If results are further passed to some methods used in final projection, you'll get the exception.

Another good idea is to try to re-execute the query logged by SQL Profiler and study the columns there: likely, NULLs will be visible there (but actually it will be hard to identify to which part of final projection this NULL will flow - your query seems pretty complex to be analyzed even when it's written as expression).


> The good news is that the speed is 3x-4x the speed of LINQ to SQL because it produces 3 SQL queries as opposed to 1 + (n * rows) produced by LINQ to SQL.

We actually use very similar approach, but the difference is that all additional queries are executed in batches during enumeration of original query result.

So in the end, you might get more then 3 SQL queries, but this will be anyway N times less than with LINQ to SQL (by default, N = batch size = 25).

> However, I'm not sure if the DO materialization should have required the null check where it does.... LINQ to SQL does not throw a null reference exception and I'm not sure LINQ to memory would do it either...

Likely, there is a difference with LINQ 2 SQL: I mentioned we try to handle final projection expressions on the client. Btw, this allows you to use simply untranslatable expressions, if they are part of the final projection expression. But as you see now, this can be a disadvantage as well.

I'll talk with our LINQ guys - probably, we must change this. LINQ in DO4 is relatively new, so there are many features like this one we aren't fully sure for. The good thing is what we can fix anything, and are ready to do this, especially if practice shows the decision we've made wasn't good.

answered Mar 11 '10 at 18:21

Alex%20Yakunin's gravatar image

Alex Yakunin
29714412

JeffN wrote: I think I follow about the materialization except I don't see anything that would cause that in my query and the same query works ok with linq to SQL.

How can I figure out the problem here?

Thank you.

(Mar 11 '10 at 18:21) Editor Editor's gravatar image
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

Subscription:

Once you sign in you will be able to subscribe for any updates here

Tags:

×574

Asked: Mar 10 '10 at 22:31

Seen: 29,375 times

Last updated: Mar 10 '10 at 22:31

powered by OSQA