2

I am trying to exclude a relationship from a database query using linq in Entity Framework Core.

I have a database where I have a table of Bills and a table of Vendors.

  • Each Bill has 1 Vendor
  • Each Vendor has many Bills

I want to exclude the List<Bill> from the Vendor while maintaining the Vendor information for the Bill I am querying. So I can gather Vendor information from that specific Bill. I currently have the relation as below.

foundBills = db_context.Bills.Include(v => v.Vendor).Where(searchLambda).ToList();

Is there a .Exclude or .Intersect or something that I am missing to exclude the circular relationship? It is using way too much memory.

Norcel
  • 53
  • 6
  • 1
    Hi and welcome on SO! Please read the [how-to-ask page](https://stackoverflow.com/help/how-to-ask) and read [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/minimal-reproducible-example) to improve your question and help us to understand your problem. – nilsK Jul 23 '20 at 14:54
  • What is searchLambda in this context. – yugami Jul 23 '20 at 15:16
  • lets say b => b.InvoiceNumber.Contains(invoiceNumber) It's really any search of a Bill property – Norcel Jul 23 '20 at 15:19
  • Use following to flatten list to make it easier to process : var bills = db_context.Vendor.SelectMany(x => x.Select(y => y.Bills)).ToList(); – jdweng Jul 23 '20 at 15:41
  • The x => x.Select inside the 'SelectMany' won't work. – Norcel Jul 23 '20 at 15:48
  • Also in EF core, relationship fixup happens and can't be stopped. – Gert Arnold Jul 25 '20 at 18:45

1 Answers1

1

If you configured your Bill and Vendor Model classes correctly for "One to Many" relationship, they should look like this:

public class Vendor
{
    // ... other properties

    public Bill Bill { get; set; }
}

public class Bill
{
    // ... other properties

    public ICollection<Vendor> Vendors { get; set; }
}

With this logic, there shouldn't be any circular dependency, because this is how it works.

Later you can use Include or not, but if you want to not have a Bill information in your Vendor for the final output then create separate models for Vendor and Bill:

public class BillOutput
{
    public List<VendorOutput> Vendors { get; set; }
}


public class VendorOutput
{
    // ... other properties
}

and later:

var finalOutput = db_context.Bills.Include(v => v.Vendor).Where(searchLambda).
                      Select(items => new BillOutput
                      {
                          Vendors = items.Select(item => new VendorOutput
                          {
                              // here you don't have the Bill Information
                          }
                      } )
                     .ToList();
Arsen Khachaturyan
  • 7,904
  • 4
  • 42
  • 42
  • 1
    *there shouldn't be any circular dependency* -- Well, it *is* a circular dependency and EF will populate both properties as much as possible even if only one is included. But you're right in recommending projection to a custom class. One remark: `Include` isn't necessary in the last statement, it will be ignore because of the projection. – Gert Arnold Jul 25 '20 at 18:47