C# question about retrieving fields

This is kind of basic but I’m trying to update a BPM that was written by consultants to better suit our needs, but my grasp of C# is not strong. Maybe someone here can assist.

This is what I have so far inside a BPM that is looping through all Assemblies on a job doing some checks.

 // Finished Part    
var finishedPart = Db.Part.Where(x =>
                                 x.Company == ttLabor.Company && 
                                 x.PartNum == jobAssembly.PartNum); 

Does that mean I have an object of type part?

I really want to do something like this:
if( finishedPart.ClassID != "KIT" ) { ... do stuff ... }

But I get ‘|Queryable’ does not contain a definition for ‘ClassID’ and no extension method ‘ClassID’ accepting a first argument of type ‘!Queryable’ could be found ( are you missing a using directive or assembly reference)

Is the syntax wrong or do I have to include something outside to be able to access part.

need to add your select statement from the query

Here are some examples (there are also a bunch on this forum)

/*Join several tables with Linq*/

/*Dictionary queue holds to-be-send emails*/
Dictionary<int, object[]> queue = new Dictionary<int, object[]>();

foreach(var quote in (from q in Db.QuoteHed.With(LockHint.NoLock)
                              
                    /*Join QSalesRp, get SalesRepCode*/
                    join r in Db.QSalesRP.With(LockHint.NoLock)
                      on new { q.Company, q.QuoteNum } equals new { r.Company, r.QuoteNum }
                      
                    /*Join SalesRp to QSalesRP, get EmailAddress*/
                    join s in Db.SalesRep.With(LockHint.NoLock)
                      on new {r.Company, r.SalesRepCode} equals new {s.Company, s.SalesRepCode}
                      
                    /*Join Customer to QuoteHed, get Name*/
                    join c in Db.Customer.With(LockHint.NoLock)
                      on new {q.Company, q.CustNum} equals new {c.Company, c.CustNum}
                      
                    where
                    q.Company == Session.CompanyID 
                    && q.FollowUpDate == DateTime.Today
                    && r.PrimeRep == true
                   
                    select new {
                      q.QuoteNum, q.FollowUpDate, s.EMailAddress, c.Name
                      }
                    ))
                    /*Start Iteration Action*/
                    {
                      if(quote != null)
                      {
                        queue.Add(quote.QuoteNum, new object[] {quote.EMailAddress, quote.FollowUpDate, quote.Name});
                      }
                    }
                    /*End Interation Action*/



/*Iterate over QuoteDtl recs*/
    foreach (var QuoteDtl_iterator in 
    	(from QuoteDtl_Row in Db.QuoteDtl
       where QuoteDtl_Row.Company == Session.CompanyID && 
    	 QuoteDtl_Row.QuoteNum == callContextBpmData.Number01
    	 select QuoteDtl_Row))
     
    	{
    		QuoteDtl = QuoteDtl_iterator;
        OrderDtl = (from OrderDtl_Row in Db.OrderDtl
        where OrderDtl_Row.Company == Session.CompanyID &&
        OrderDtl_Row.OrderNum == orderNum &&
        OrderDtl_Row.OrderLine == LineNum
        select OrderDtl_Row).FirstOrDefault();

            if (OrderDtl != null)
            {
               //do something
            }
	
   }

This is what we got working:

 var finishedPartClass = Db.Part.Where(x =>
                                 x.Company == ttLabor.Company && 
                                 x.PartNum == jobAssembly.PartNum &&
                                 x.AssemblySeq == jobAssembly.AssemblySeq )
                            .First().ClassID;

That will just select that field, FYI. Which is probably what you wanted, but just so you know

I would probably re-write the code to the following:

var finishedPartClass = Db.Part.Where(x =>
x.Company == ttLabor.Company &&
x.PartNum == jobAssembly.PartNum &&
x.AssemblySeq == jobAssembly.AssemblySeq )
.FirstOrDefault();

if (finishedPartClass != null)
{
finishedPartClass .ClassID = [your classID value];
}

This will ensure finishedPartClass contains an instance of an object before attempting to assign a value. If it doesn’t find a finished part based on your filter criteria, finishedPartClass will return null and no value will be assigned.

if you asked me a year ago, i would have provided a similar answer to @jbrekke… but for reasons of database efficiency, I have learned that you dont want to retrieve the entire data record ESPECIALLY if you only want one value… you can also eliminate the “instance of an object” error another way.
Here is how I would retrieve just the partclass of the part (if you only want that one field. Note that I am using the double question ?? operator, which is a “null-coalescing” operator… basically it says: “If the returned value is null, then use this value instead”. That way you don’t get the “instance of an object” error.
Note also that we are simply defining the string partClass, and only returning that one value instead of the entire part record. This will add to your efficiency.

string partClass = Db.Part.Where(x =>
    x.Company == ttLabor.Company &&
    x.PartNum == jobAssembly.PartNum &&
    x.AssemblySeq == jobAssembly.AssemblySeq ).Select( x=>x.ClassID)
   .FirstOrDefault() ?? "@@@";
if (partClass != "@@@" {
  //your part class is in the string variable partClass, and you can do something here
}
2 Likes