0

Is there a way I have have this linq statement not return nulls ? I would like it to returns 0 I have tried ?? 0 but that is not working

    Customer = (from c in db.Customers
                  join cx in db.CustomerXrefs on c.CustomerId equals cx.CustomerId
                  join g in db.Groups on cx.GroupId equals g.GroupId
                  select new Customer
                  {
                      CustomerId = c.CustomerId,
                      Institution = (from ig in db.Groups
                                     join icx in db.CustomerXrefs on ig.GroupId equals icx.GroupId
                                     where icx.CustomerId == c.CustomerId && ig.GroupTypeId == 308
                                     select new Institution()
                                     {
                                         Name = ig.Name == "In1 " ? "Institution 1" :
                                                ig.Name == "In2" ? "Institution 2" :
                                                ig.Name
                                     }
                                     ).FirstOrDefault()
                  }).FirstOrDefault();
6
  • What property is coming null? Commented Jul 6, 2020 at 14:12
  • Customer is null Commented Jul 6, 2020 at 14:16
  • So you want Customer to be 0? Commented Jul 6, 2020 at 14:19
  • that is correct Commented Jul 6, 2020 at 14:21
  • 1
    @Jefferson, try doing Customer myCustomer = 0; or Institution myInstitution = 0; and see what you get. What you are asking makes no sense, and makes me think there are lots of things to fix in your code. Commented Jul 6, 2020 at 14:31

2 Answers 2

1

It is a bit difficult to distill from your question what you want to achieve. You give us some code, and tell us that the code doesn't do what you want, and ask us to give you the code that does give the requested result.

I hope I can extract your requirement from your code.

It seems that you have a table of Customers and a table of Groups. There seems to be a many-to-many relation between Customers and Groups: every Customer belongs to zero or more Groups, every Group has zero or more Customers that belong to this Group.

In relational databases, a many-to-many relation is implemented using a junction table. The junction table for the many-to-many between Customers and Groups is table CustomerXRefs

For every Customer in the table of Customers, you want its CustomerId, and a Property Institution.

The value of Institution is filled with a Name. This name is taken from the first Group of this Customer with GroupTypeId equal to 308.

There are two solutions for this:

  • Use GroupJoins to get the Customers with their Groups and extract the Institution from these groups
  • Use the capability of entity framework to translate the virtual ICollection<...> into the corrrect GroupJoins. Use the virtual properties, entity framework translates them into the proper GroupJoin.

Usually the latter solution is easier, so we'll start with that one first.

The classes

If you have followed the entity framework conventions, you'll have classes similar to the following:

class Customer
{
    public int Id {get; set;}
    ...  // other properties

    // every Customer belongs to zero or more Groups (many-to-many)
    public virtual ICollection<Group> Groups {get; set;}
}

class Group
{
    public int Id {get; set;}
    public int GroupTypeId {get; set;}
    public string Name {get; set;}
    ...  // other properties

    // every Group has to zero or more Customers(many-to-many)
    public virtual ICollection<Customer> Customers {get; set;}
}

This is enough for entity framework to detect your many-to-many relation. Without even mentioning it, entity framework will create a junction table for you. Only if you want different names of tables or properties, you'll need fluent API or attributes.

In entity framework the columns of the table are represented by non-virtual properties; the virtual properties represent the relations between the tables: one-to-many, many-to-many, ...

Query using the virtual ICollection

var customersWithTheirGroups = dbContext.Customers.Select(customer => new
{
    CustomerId = customer.Id,
    Institution = customer.Groups.Where(group => group.GroupTypeId == 308)
        .Select(group => new Institution
        {
            name = (ig.Name == "In1") ? "Institution 1" :
                   (ig.Name == "In2") ? "Institution 2  :
                    ig.Name,
        })
        .FirstOrDefault(),
});

BTW: note the parentheses around (ig.Name == "In1"). I think that if Name equals "In1" that you want a name "Institution 1", etc.

Is it correct that you have a class Institution with only one property?

class Institution
{
    public string Name {get; set;}
}

Although it is allowed, it is a bit awkward, why not just select the InstitutionName?

.Select(group => (ig.Name == "In1") ? "Institution 1" :
                 (ig.Name == "In2") ? "Institution 2  :
                  ig.Name)
.FirstOrDefault(),

Anyway, entity framework knows the relations between the tables and will create the correct groupjoins with the junction tables.

This solution seems very natural.

Solution using GroupJoins

If you want to do the GroupJoin yourself, you'll need to define the junction table:

class CustomerXrefs
{
    // every Xref in the junction table belongs to exactly one Customer:        
    public int CustomerId {get; set;}

    // every Xref in the junction table belongs to exactly one Group:
    public int GroupId {get; set;}
}

To get each Customer with its Groups, do a GroupJoin of the XRefs with the Customers, followed by another GroupJoin of Groups and XRefs.

var customersWithTheirGroups = dbContext.Customers.GroupJoin(dbContext.CustomerXRefs,
    customer => customer.Id,           // from every Customer take the Id
    xref => xref.CustomerId,           // from every xref take the foreign key to Customer

    // Parameter resultSelector:
    // for every Customer and all its xrefs make one new object:
    (customer, xrefsOfThisCustomer) => new 
    {
        Customer = customer,

        // To get the Groups of this customer, GroupJoin the Groups with the xrefs:
        Groups = dbContext.Groups

            // GroupJoin the Group with the xrefs of this Customer
            .GroupJoin(xrefsOfThisCustomer,
            group => group.Id,      // for every Group take the Id,
            xRef => xref.GroupId,   // for every xref of this customer take the foreign key

            // parameter resultSelector:
            // for every Group, and all xrefs of this Group that are xrefs of the Customer
            // make one new:
            (group, xrefs) => group).ToList(),
    });

Result: all Customers, each with their Groups.

Select the institution:

var result = customersWithTheirGroups.Select(joinResult => new
{
    CustomerId = joinResult.Customer.Id,

    Institution = joinResult.Groups
        // Keep only the Groups with the desired GroupTypeId
        .Where(group => group.GroupTypeId == 308)

        // The Select is similar as the Select in the virtual ICollection method:
        .Select(group => new Institution
        {
            name = (ig.Name == "In1") ? "Institution 1" :
                   (ig.Name == "In2") ? "Institution 2  :
                    ig.Name,
        })
        .FirstOrDefault(),
    });
Sign up to request clarification or add additional context in comments.

Comments

1

Customer is a class (reference type). Default value for a reference type is null. If you want to return some non null value (if there exists correct "default" for your use case) you will need to provide one, for example:

Customer = (...).FirstOrDefault() ?? new Customer();

7 Comments

We'd better first ask the OP what they actually want. Because what does returning a new Customer() achieve? Now instead of the caller checking for null, the caller will now have to determine whether this is a "default instance", so for example if (c.Name != null) { ... }...
I agree. It seems to me OP is just trying to avoid a null reference exception and not caring about what will happen next.
I was just looking for 0 for both models Customer and Institution? can I do something like ?? 0?
A class cannot be just "zero". It must be a valid value for that class, like Guru explained. It's not an int. Your problem might be bigger than what you think.
@Jefferson for me it would be strange if GetCustomerId returns Customer not just id.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.