multiple method left extension ejemplos conditions c# linq join

c# - method - IZQUIERDA UNIRSE EXTERIOR EN LINQ



left join linq c# ejemplos (20)

¿Cómo realizar la combinación externa izquierda en C # LINQ a los objetos sin utilizar cláusulas de join-on-equals-into ? ¿Hay alguna manera de hacer eso con la cláusula de where ? Problema correcto: para la unión interna es fácil y tengo una solución como esta

List<JoinPair> innerFinal = (from l in lefts from r in rights where l.Key == r.Key select new JoinPair { LeftId = l.Id, RightId = r.Id})

pero para la unión externa izquierda necesito una solución. El mío es algo así, pero no funciona.

List< JoinPair> leftFinal = (from l in lefts from r in rights select new JoinPair { LeftId = l.Id, RightId = ((l.Key==r.Key) ? r.Id : 0 })

donde JoinPair es una clase:

public class JoinPair { long leftId; long rightId; }


Ahora como un método de extensión:

public static class LinqExt { public static IEnumerable<TResult> LeftOuterJoin<TLeft, TRight, TKey, TResult>(this IEnumerable<TLeft> left, IEnumerable<TRight> right, Func<TLeft, TKey> leftKey, Func<TRight, TKey> rightKey, Func<TLeft, TRight, TResult> result) { return left.GroupJoin(right, leftKey, rightKey, (l, r) => new { l, r }) .SelectMany( o => o.r.DefaultIfEmpty(), (l, r) => new { lft= l.l, rght = r }) .Select(o => result.Invoke(o.lft, o.rght)); } }

Use como usaría normalmente unir:

var contents = list.LeftOuterJoin(list2, l => l.country, r => r.name, (l, r) => new { count = l.Count(), l.country, l.reason, r.people })

Espero que esto te ahorre tiempo.


Aquí hay un ejemplo si necesita unir más de 2 tablas:

from d in context.dc_tpatient_bookingd join bookingm in context.dc_tpatient_bookingm on d.bookingid equals bookingm.bookingid into bookingmGroup from m in bookingmGroup.DefaultIfEmpty() join patient in dc_tpatient on m.prid equals patient.prid into patientGroup from p in patientGroup.DefaultIfEmpty()

Ref: https://.com/a/17142392/2343


Aquí hay una versión bastante fácil de entender usando la sintaxis del método:

IEnumerable<JoinPair> outerLeft = lefts.SelectMany(l => rights.Where(r => l.Key == r.Key) .DefaultIfEmpty(new Item()) .Select(r => new JoinPair { LeftId = l.Id, RightId = r.Id }));


Como se indica en:

101 Muestras LINQ - Unión externa izquierda

var q = from c in categories join p in products on c.Category equals p.Category into ps from p in ps.DefaultIfEmpty() select new { Category = c, ProductName = p == null ? "(No products)" : p.ProductName };


Echa un vistazo a este example . Esta consulta debería funcionar:

var leftFinal = from left in lefts join right in rights on left equals right.Left into leftRights from leftRight in leftRights.DefaultIfEmpty() select new { LeftId = left.Id, RightId = left.Key==leftRight.Key ? leftRight.Id : 0 };


Esta es la forma general (como ya se proporciona en otras respuestas)

var c = from a in alpha join b in beta on b.field1 equals a.field1 into b_temp from b_value in b_temp.DefaultIfEmpty() select new { Alpha = a, Beta = b_value };

Sin embargo, aquí hay una explicación que espero que aclare lo que realmente significa.

join b in beta on b.field1 equals a.field1 into b_temp

esencialmente crea un conjunto de resultados separado b_temp que incluye efectivamente "filas" nulas para las entradas en el lado derecho (entradas en ''b'').

Luego la siguiente línea:

from b_value in b_temp.DefaultIfEmpty()

.. se escribe sobre ese conjunto de resultados, establece el valor nulo predeterminado para la ''fila'' en el lado derecho y establece el resultado de la fila del lado derecho unida al valor de ''b_value'' (es decir, el valor que está a la derecha lado de la mano, si hay un registro coincidente, o ''nulo'' si no lo hay).

Ahora, si el lado derecho es el resultado de una consulta LINQ por separado, constará de tipos anónimos, que solo pueden ser ''algo'' o ''nulos''. Sin embargo, si es una enumeración (por ejemplo, una Lista, donde MyObjectB es una clase con 2 campos), es posible ser específico sobre qué valores ''nulos'' predeterminados se usan para sus propiedades:

var c = from a in alpha join b in beta on b.field1 equals a.field1 into b_temp from b_value in b_temp.DefaultIfEmpty( new MyObjectB { Field1 = String.Empty, Field2 = (DateTime?) null }) select new { Alpha = a, Beta_field1 = b_value.Field1, Beta_field2 = b_value.Field2 };

Esto garantiza que ''b'' no sea nulo (pero sus propiedades pueden ser nulas, usando los valores nulos predeterminados que ha especificado), y esto le permite verificar las propiedades de b_value sin obtener una excepción de referencia nula para b_value. Tenga en cuenta que para un DateTime anulable, un tipo de (DateTime?), Es decir, ''DateTime anulable'' debe especificarse como el ''Tipo'' del nulo en la especificación para ''DefaultIfEmpty'' (esto también se aplicará a los tipos que no son ''nativos ''anulable por ejemplo doble, flotador).

Puede realizar varias combinaciones externas a la izquierda simplemente encadenando la sintaxis anterior.


Esta es una sintaxis SQL comparada con la sintaxis LINQ para uniones internas internas y externas. Izquierda combinación externa:

http://www.ozkary.com/2011/07/linq-to-entity-inner-and-left-joins.html

"El siguiente ejemplo hace una unión grupal entre producto y categoría. Esta es esencialmente la combinación izquierda. La expresión into devuelve datos incluso si la tabla de categorías está vacía. Para acceder a las propiedades de la tabla de categorías, ahora debemos seleccionar el resultado enumerable agregando el from cl en la sentencia catList.DefaultIfEmpty ().


Hay tres tablas: personas, escuelas y escuelas de personas, que conectan a las personas con las escuelas en las que estudian. Una referencia a la persona con id = 6 está ausente en la tabla de personas-escuelas. Sin embargo, la persona con id = 6 se presenta en el resultado de la cuadrícula unida.

List<Person> persons = new List<Person> { new Person { id = 1, name = "Alex", phone = "4235234" }, new Person { id = 2, name = "Bob", phone = "0014352" }, new Person { id = 3, name = "Sam", phone = "1345" }, new Person { id = 4, name = "Den", phone = "3453452" }, new Person { id = 5, name = "Alen", phone = "0353012" }, new Person { id = 6, name = "Simon", phone = "0353012" } }; List<School> schools = new List<School> { new School { id = 1, name = "Saint. John''s school"}, new School { id = 2, name = "Public School 200"}, new School { id = 3, name = "Public School 203"} }; List<PersonSchool> persons_schools = new List<PersonSchool> { new PersonSchool{id_person = 1, id_school = 1}, new PersonSchool{id_person = 2, id_school = 2}, new PersonSchool{id_person = 3, id_school = 3}, new PersonSchool{id_person = 4, id_school = 1}, new PersonSchool{id_person = 5, id_school = 2} //a relation to the person with id=6 is absent }; var query = from person in persons join person_school in persons_schools on person.id equals person_school.id_person into persons_schools_joined from person_school_joined in persons_schools_joined.DefaultIfEmpty() from school in schools.Where(var_school => person_school_joined == null ? false : var_school.id == person_school_joined.id_school).DefaultIfEmpty() select new { Person = person.name, School = school == null ? String.Empty : school.name }; foreach (var elem in query) { System.Console.WriteLine("{0},{1}", elem.Person, elem.School); }


Método de extensión que funciona como unir a la izquierda con la sintaxis Unir

public static class LinQExtensions { public static IEnumerable<TResult> LeftJoin<TOuter, TInner, TKey, TResult>( this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector) { return outer.GroupJoin( inner, outerKeySelector, innerKeySelector, (outerElement, innerElements) => resultSelector(outerElement, innerElements.FirstOrDefault())); } }

lo escribí en .NET core y parece estar funcionando como se esperaba.

Pequeña prueba:

var Ids = new List<int> { 1, 2, 3, 4}; var items = new List<Tuple<int, string>> { new Tuple<int, string>(1,"a"), new Tuple<int, string>(2,"b"), new Tuple<int, string>(4,"d"), new Tuple<int, string>(5,"e"), }; var result = Ids.LeftJoin( items, id => id, item => item.Item1, (id, item) => item ?? new Tuple<int, string>(id, "not found")); result.ToList() Count = 4 [0]: {(1, a)} [1]: {(2, b)} [2]: {(3, not found)} [3]: {(4, d)}


Me gustaría agregar que si obtiene la extensión MoreLinq, ahora hay soporte para uniones homogéneas y heterogéneas de izquierda ahora

http://morelinq.github.io/2.8/ref/api/html/Overload_MoreLinq_MoreEnumerable_LeftJoin.htm

ejemplo:

//Pretend a ClientCompany object and an Employee object both have a ClientCompanyID key on them return DataContext.ClientCompany .LeftJoin(DataContext.Employees, //Table being joined company => company.ClientCompanyID, //First key employee => employee.ClientCompanyID, //Second Key company => new {company, employee = (Employee)null}, //Result selector when there isn''t a match (company, employee) => new { company, employee }); //Result selector when there is a match

EDITAR:

En retrospectiva, esto puede funcionar, pero convierte el IQueryable en un IEnumerable como morelinq no convierte la consulta a SQL.

En su lugar, puede usar un GroupJoin como se describe aquí: https://.com/a/24273804/4251433

Esto asegurará que permanezca como un IQueryable en caso de que necesite realizar más operaciones lógicas en él más adelante.


Nigromancia.
Si se utiliza un proveedor LINQ basado en la base de datos, se puede escribir una combinación externa izquierda mucho más legible como tal:

from maintable in Repo.T_Whatever from xxx in Repo.T_ANY_TABLE.Where(join condition).DefaultIfEmpty()

Si omite el DefaultIfEmpty() tendrá una unión interna.

Toma la respuesta aceptada:

from c in categories join p in products on c equals p.Category into ps from p in ps.DefaultIfEmpty()

Esta sintaxis es muy confusa, y no está claro cómo funciona cuando se quiere unir las tablas MÚLTIPLES.

Nota
Cabe señalar que a from alias in Repo.whatever.Where(condition).DefaultIfEmpty() es lo mismo que una aplicación externa / from alias in Repo.whatever.Where(condition).DefaultIfEmpty() -lateral-lateral, que cualquier optimizador de base de datos (decente) es perfectamente capaz de traducir a unirse a la izquierda, siempre y cuando no introduzcas valores por fila (es decir, una aplicación externa real). No hagas esto en Linq-2-Objects (porque no hay DB-optimizer cuando usas Linq-to-Objects).

Ejemplo detallado

var query2 = ( from users in Repo.T_User from mappings in Repo.T_User_Group .Where(mapping => mapping.USRGRP_USR == users.USR_ID) .DefaultIfEmpty() // <== makes join left join from groups in Repo.T_Group .Where(gruppe => gruppe.GRP_ID == mappings.USRGRP_GRP) .DefaultIfEmpty() // <== makes join left join // where users.USR_Name.Contains(keyword) // || mappings.USRGRP_USR.Equals(666) // || mappings.USRGRP_USR == 666 // || groups.Name.Contains(keyword) select new { UserId = users.USR_ID ,UserName = users.USR_User ,UserGroupId = groups.ID ,GroupName = groups.Name } ); var xy = (query2).ToList();

Cuando se usa con LINQ 2 SQL, se traducirá muy bien a la siguiente consulta SQL muy legible:

SELECT users.USR_ID AS UserId ,users.USR_User AS UserName ,groups.ID AS UserGroupId ,groups.Name AS GroupName FROM T_User AS users LEFT JOIN T_User_Group AS mappings ON mappings.USRGRP_USR = users.USR_ID LEFT JOIN T_Group AS groups ON groups.GRP_ID == mappings.USRGRP_GRP

Editar:

Consulte también " Convertir la consulta de SQL Server en una consulta de Linq " para ver un ejemplo más complejo.

Además, si lo está haciendo en Linq-2-Objects (en lugar de Linq-2-SQL), debe hacerlo de la manera antigua (porque LINQ to SQL traduce esto correctamente para unir operaciones, pero sobre los objetos este método fuerza un escaneo completo, y no aprovecha las búsquedas de índice, por qué ...):

var query2 = ( from users in Repo.T_Benutzer join mappings in Repo.T_Benutzer_Benutzergruppen on mappings.BEBG_BE equals users.BE_ID into tmpMapp join groups in Repo.T_Benutzergruppen on groups.ID equals mappings.BEBG_BG into tmpGroups from mappings in tmpMapp.DefaultIfEmpty() from groups in tmpGroups.DefaultIfEmpty() select new { UserId = users.BE_ID ,UserName = users.BE_User ,UserGroupId = mappings.BEBG_BG ,GroupName = groups.Name } );


Realizar combinaciones externas a la izquierda en linq C # // Realizar combinaciones externas a la izquierda

class Person { public string FirstName { get; set; } public string LastName { get; set; } } class Child { public string Name { get; set; } public Person Owner { get; set; } } public class JoinTest { public static void LeftOuterJoinExample() { Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" }; Person terry = new Person { FirstName = "Terry", LastName = "Adams" }; Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" }; Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" }; Child barley = new Child { Name = "Barley", Owner = terry }; Child boots = new Child { Name = "Boots", Owner = terry }; Child whiskers = new Child { Name = "Whiskers", Owner = charlotte }; Child bluemoon = new Child { Name = "Blue Moon", Owner = terry }; Child daisy = new Child { Name = "Daisy", Owner = magnus }; // Create two lists. List<Person> people = new List<Person> { magnus, terry, charlotte, arlene }; List<Child> childs = new List<Child> { barley, boots, whiskers, bluemoon, daisy }; var query = from person in people join child in childs on person equals child.Owner into gj from subpet in gj.DefaultIfEmpty() select new { person.FirstName, ChildName = subpet!=null? subpet.Name:"No Child" }; // PetName = subpet?.Name ?? String.Empty }; foreach (var v in query) { Console.WriteLine($"{v.FirstName + ":",-25}{v.ChildName}"); } } // This code produces the following output: // // Magnus: Daisy // Terry: Barley // Terry: Boots // Terry: Blue Moon // Charlotte: Whiskers // Arlene: No Child

https://dotnetwithhamid.blogspot.in/


Si necesita unirse y filtrar en algo, eso puede hacerse fuera de la unión. El filtro se puede hacer después de crear la colección.

En este caso, si hago esto en la condición de unión, reduzco las filas que se devuelven.

Se usa la condición ternaria (= n == null ? "__" : n.MonDayNote,)

  • Si el objeto es null (no coincide), devuelva lo que está después de ? . __ , en este caso.

  • Si no, devuelve lo que está después de : n.MonDayNote .

Gracias a los otros colaboradores, es donde comencé con mi propio problema.

var schedLocations = (from f in db.RAMS_REVENUE_LOCATIONS join n in db.RAMS_LOCATION_PLANNED_MANNING on f.revenueCenterID equals n.revenueCenterID into lm from n in lm.DefaultIfEmpty() join r in db.RAMS_LOCATION_SCHED_NOTE on f.revenueCenterID equals r.revenueCenterID into locnotes from r in locnotes.DefaultIfEmpty() where f.LocID == nLocID && f.In_Use == true && f.revenueCenterID > 1000 orderby f.Areano ascending, f.Locname ascending select new { Facname = f.Locname, f.Areano, f.revenueCenterID, f.Locabbrev, // MonNote = n == null ? "__" : n.MonDayNote, MonNote = n == null ? "__" : n.MonDayNote, TueNote = n == null ? "__" : n.TueDayNote, WedNote = n == null ? "__" : n.WedDayNote, ThuNote = n == null ? "__" : n.ThuDayNote, FriNote = n == null ? "__" : n.FriDayNote, SatNote = n == null ? "__" : n.SatDayNote, SunNote = n == null ? "__" : n.SunDayNote, MonEmpNbr = n == null ? 0 : n.MonEmpNbr, TueEmpNbr = n == null ? 0 : n.TueEmpNbr, WedEmpNbr = n == null ? 0 : n.WedEmpNbr, ThuEmpNbr = n == null ? 0 : n.ThuEmpNbr, FriEmpNbr = n == null ? 0 : n.FriEmpNbr, SatEmpNbr = n == null ? 0 : n.SatEmpNbr, SunEmpNbr = n == null ? 0 : n.SunEmpNbr, SchedMondayDate = n == null ? dMon : n.MondaySchedDate, LocNotes = r == null ? "Notes: N/A" : r.LocationNote }).ToList(); Func<int, string> LambdaManning = (x) => { return x == 0 ? "" : "Manning:" + x.ToString(); }; DataTable dt_ScheduleMaster = PsuedoSchedule.Tables["ScheduleMasterWithNotes"]; var schedLocations2 = schedLocations.Where(x => x.SchedMondayDate == dMon);


Solución simple para la IZQUIERDA EXTERIOR IZQUIERDA

var setA = context.SetA; var setB = context.SetB.Select(st=>st.Id).Distinct().ToList(); var leftOuter = setA.Where(stA=> !setB.Contains(stA.Id));

notas :

  • Para mejorar el rendimiento, SetB se puede convertir en un Diccionario (si se hace, entonces debe cambiar esto :! SetB.Contains (stA.Id) ) o un HashSet
  • Cuando hay más de un campo involucrado, esto podría lograrse utilizando operaciones de Set y una clase que implemente: IEqualityComparer

Una implementación de la combinación externa izquierda por métodos de extensión podría verse como

public static IEnumerable<Result> LeftJoin<TOuter, TInner, TKey, Result>( this IEnumerable<TOuter> outer, IEnumerable<TInner> inner , Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector , Func<TOuter, TInner, Result> resultSelector, IEqualityComparer<TKey> comparer) { if (outer == null) throw new ArgumentException("outer"); if (inner == null) throw new ArgumentException("inner"); if (outerKeySelector == null) throw new ArgumentException("outerKeySelector"); if (innerKeySelector == null) throw new ArgumentException("innerKeySelector"); if (resultSelector == null) throw new ArgumentException("resultSelector"); return LeftJoinImpl(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer ?? EqualityComparer<TKey>.Default); } static IEnumerable<Result> LeftJoinImpl<TOuter, TInner, TKey, Result>( IEnumerable<TOuter> outer, IEnumerable<TInner> inner , Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector , Func<TOuter, TInner, Result> resultSelector, IEqualityComparer<TKey> comparer) { var innerLookup = inner.ToLookup(innerKeySelector, comparer); foreach (var outerElment in outer) { var outerKey = outerKeySelector(outerElment); var innerElements = innerLookup[outerKey]; if (innerElements.Any()) foreach (var innerElement in innerElements) yield return resultSelector(outerElment, innerElement); else yield return resultSelector(outerElment, default(TInner)); } }

El selector de resultados tiene que ocuparse de los elementos nulos. Fx.

static void Main(string[] args) { var inner = new[] { Tuple.Create(1, "1"), Tuple.Create(2, "2"), Tuple.Create(3, "3") }; var outer = new[] { Tuple.Create(1, "11"), Tuple.Create(2, "22") }; var res = outer.LeftJoin(inner, item => item.Item1, item => item.Item1, (it1, it2) => new { Key = it1.Item1, V1 = it1.Item2, V2 = it2 != null ? it2.Item2 : default(string) }); foreach (var item in res) Console.WriteLine(string.Format("{0}, {1}, {2}", item.Key, item.V1, item.V2)); }


Usando la expresión lambda

db.Categories .GroupJoin( db.Products, Category => Category.CategoryId, Product => Product.CategoryId, (x, y) => new { Category = x, Products = y }) .SelectMany( xy => xy.Products.DefaultIfEmpty(), (x, y) => new { Category = x.Category, Product = y }) .Select(s => new { CategoryName = s.Category.Name, ProductName = s.Product.Name })


mira este ejemplo

class Person { public int ID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Phone { get; set; } } class Pet { public string Name { get; set; } public Person Owner { get; set; } } public static void LeftOuterJoinExample() { Person magnus = new Person {ID = 1, FirstName = "Magnus", LastName = "Hedlund"}; Person terry = new Person {ID = 2, FirstName = "Terry", LastName = "Adams"}; Person charlotte = new Person {ID = 3, FirstName = "Charlotte", LastName = "Weiss"}; Person arlene = new Person {ID = 4, FirstName = "Arlene", LastName = "Huff"}; Pet barley = new Pet {Name = "Barley", Owner = terry}; Pet boots = new Pet {Name = "Boots", Owner = terry}; Pet whiskers = new Pet {Name = "Whiskers", Owner = charlotte}; Pet bluemoon = new Pet {Name = "Blue Moon", Owner = terry}; Pet daisy = new Pet {Name = "Daisy", Owner = magnus}; // Create two lists. List<Person> people = new List<Person> {magnus, terry, charlotte, arlene}; List<Pet> pets = new List<Pet> {barley, boots, whiskers, bluemoon, daisy}; var query = from person in people where person.ID == 4 join pet in pets on person equals pet.Owner into personpets from petOrNull in personpets.DefaultIfEmpty() select new { Person=person, Pet = petOrNull}; foreach (var v in query ) { Console.WriteLine("{0,-15}{1}", v.Person.FirstName + ":", (v.Pet == null ? "Does not Exist" : v.Pet.Name)); } } // This code produces the following output: // // Magnus: Daisy // Terry: Barley // Terry: Boots // Terry: Blue Moon // Charlotte: Whiskers // Arlene:

Ahora puede include elements from the left incluso si ese elemento has no matches in the right , en nuestro caso, hemos recuperado a Arlene incluso si no tiene coincidencias en la derecha.

aqui esta la referencia

Cómo: Realizar uniones externas izquierdas (Guía de programación de C #)


(from a in db.Assignments join b in db.Deliveryboys on a.AssignTo equals b.EmployeeId //from d in eGroup.DefaultIfEmpty() join c in db.Deliveryboys on a.DeliverTo equals c.EmployeeId into eGroup2 from e in eGroup2.DefaultIfEmpty() where (a.Collected == false) select new { OrderId = a.OrderId, DeliveryBoyID = a.AssignTo, AssignedBoyName = b.Name, Assigndate = a.Assigndate, Collected = a.Collected, CollectedDate = a.CollectedDate, CollectionBagNo = a.CollectionBagNo, DeliverTo = e == null ? "Null" : e.Name, DeliverDate = a.DeliverDate, DeliverBagNo = a.DeliverBagNo, Delivered = a.Delivered });


class Program { List<Employee> listOfEmp = new List<Employee>(); List<Department> listOfDepart = new List<Department>(); public Program() { listOfDepart = new List<Department>(){ new Department { Id = 1, DeptName = "DEV" }, new Department { Id = 2, DeptName = "QA" }, new Department { Id = 3, DeptName = "BUILD" }, new Department { Id = 4, DeptName = "SIT" } }; listOfEmp = new List<Employee>(){ new Employee { Empid = 1, Name = "Manikandan",DepartmentId=1 }, new Employee { Empid = 2, Name = "Manoj" ,DepartmentId=1}, new Employee { Empid = 3, Name = "Yokesh" ,DepartmentId=0}, new Employee { Empid = 3, Name = "Purusotham",DepartmentId=0} }; } static void Main(string[] args) { Program ob = new Program(); ob.LeftJoin(); Console.ReadLine(); } private void LeftJoin() { listOfEmp.GroupJoin(listOfDepart.DefaultIfEmpty(), x => x.DepartmentId, y => y.Id, (x, y) => new { EmpId = x.Empid, EmpName = x.Name, Dpt = y.FirstOrDefault() != null ? y.FirstOrDefault().DeptName : null }).ToList().ForEach (z => { Console.WriteLine("Empid:{0} EmpName:{1} Dept:{2}", z.EmpId, z.EmpName, z.Dpt); }); } } class Employee { public int Empid { get; set; } public string Name { get; set; } public int DepartmentId { get; set; } } class Department { public int Id { get; set; } public string DeptName { get; set; } }

OUTPUT


var ResultSet = from E in DbContext.emps join D in DbContext.depts on E.deptno equals D.deptno into ps from D in ps.DefaultIfEmpty() select new { ENO = E.empno, ENAME = E.ename, SALARY = E.sal, DNO = E.deptno != null ? E.deptno : null, DNAME = D.dname, }; var FinalResultSet = ResultSet.ToList();