Issue On The Linq Query - linq
I am trying to do a very simple task with Linq and already stuck. It's really horrible but I guess, it's better to know using this post. I've two tables. One is Products and another is Ratings. Here is the demo script:
CREATE TABLE [dbo].[Products](
[ProductID] [int] IDENTITY(1,1) PRIMARY KEY,
[ProductName] [varchar](40) NULL,
[Price] [float] NULL,
[Details] [varchar](max) NULL,
[CategoryID] [int] NULL
)
INSERT [dbo].[Products] ([ProductID], [ProductName], [Price], [Details], [CategoryID]) VALUES (1, N'Denim', 1200, NULL, 1)
INSERT [dbo].[Products] ([ProductID], [ProductName], [Price], [Details], [CategoryID]) VALUES (2, N'Denim 2', 220, NULL, 1)
INSERT [dbo].[Products] ([ProductID], [ProductName], [Price], [Details], [CategoryID]) VALUES (3, N'Pringles', 240, NULL, 2)
INSERT [dbo].[Products] ([ProductID], [ProductName], [Price], [Details], [CategoryID]) VALUES (4, N'Pringles 2', 260, NULL, 2)
INSERT [dbo].[Products] ([ProductID], [ProductName], [Price], [Details], [CategoryID]) VALUES (5, N'Pringles 3', 240, NULL, 2)
CREATE TABLE [dbo].[Ratings](
[AutoId] [int] IDENTITY(1,1) PRIMARY KEY,
[ProductId] [int] NOT NULL,
[UserRating] [float] NOT NULL
)
INSERT [dbo].[Ratings] ([AutoId], [ProductId], [UserRating]) VALUES (4, 2, 1.5)
INSERT [dbo].[Ratings] ([AutoId], [ProductId], [UserRating]) VALUES (5, 4, 2.5)
INSERT [dbo].[Ratings] ([AutoId], [ProductId], [UserRating]) VALUES (6, 1, 5)
INSERT [dbo].[Ratings] ([AutoId], [ProductId], [UserRating]) VALUES (7, 2, 2.5)
And the output should be the following:
ProductId - ProductName - User Rating
1 - Denim - 5
2 - Denim 2 - 2
3 - Pringles - 0
4 - Pringles 2 - 2.5
5 - Pringles 3 - 0
This is the rating system of a project and I am trying to get the above output using Linq. With the following Sql, I got the result:
SELECT m.ProductId, m.ProductName, ISNULL(SUM(k.UserRating) / COUNT(k.ProductId), 0) AS 'User Rating' FROM Products m
LEFT JOIN Ratings k ON k.ProductId = m.ProductID
GROUP BY m.ProductID, m.ProductName
Unfortunately, with the following Linq, I get only the rating details that exist in the Ratings table:
var con = (from c in db.Ratings
join d in db.Products on c.ProductId equals d.ProductID into ps
from rt in ps.DefaultIfEmpty()
group new { c, ps } by new { rt.ProductID, rt.ProductName } into g
select new ProductRating
{
ProductId = g.Key.ProductID,
ProductName = g.Key.ProductName,
Total = g.Sum(c => c.c.UserRating) / g.Count()
}).ToList();
Note: My goal is to get the rating details (sum of a product's rating) that don't exist in the Ratings table (Should return '0' if no data) along with the ratings details that exist.
Update 1 - Class ProductRating:
public class ProductRating {
public int ProductId { get; set; }
public string ProductName { get; set; }
public double Total { get; set; } //Property for the rating
}
Update 2 - Class Products and Ratings:
public partial class Products
{
public int ProductID { get; set; }
public string ProductName { get; set; }
public Nullable<double> Price { get; set; }
public string Details { get; set; }
public Nullable<int> CategoryID { get; set; }
public ICollection<Ratings> Rating { get; set; }
}
public partial class Ratings
{
public int AutoId { get; set; }
public int ProductId { get; set; }
public double UserRating { get; set; }
}
Used the following the Linq query and got this error - The specified type member 'Rating' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported:
var con = db.Products.Select(c => new ProductRating
{
ProductId = c.ProductID,
ProductName = c.ProductName,
Total = c.Rating.Average(d => (double?)d.UserRating) ?? 0
}).ToList();
Update 3: Now getting this error - error 2016: The value specified for the condition is not compatible with the type of the member and this is how I tried for the navigation property:
Note: I've modified Andrés Robinet's query and it worked though using the Join.
from c in db.Ratings
join d in db.Products on c.ProductId equals d.ProductID into ps
from rt in ps.DefaultIfEmpty()
is the LINQ equivalent of the SQL Ratings LEFT OUTER JOIN Products, i.e. exactly the opposite of your SQL query.
While the LINQ query can be modified to match the SQL query, it doesn't make sense because EF provides a much better way which totally eliminates the need of using joins in the LINQ query - the so called navigation properties (see Don’t use Linq’s Join. Navigate!).
Normally the Product class would have a collection navigation property
public ICollection<Rating> Ratings { get; set; }
representing the one to many relationship between Product and Rating, and the equivalent LINQ query using it would be simply:
var result = db.Products
.Select(p => new ProductRating
{
ProductId = p.ProductId,
ProductName = p.ProductName,
Total = p.Ratings.Average(r => (double?)r.UserRating) ?? 0
}).ToList();
Update: In case you haven't set up correctly the relationship in the entity model, you could use the manual join equivalent of the above query by replacing the navigation property accessor with group join:
var result = (
from p in db.Products
join r in db.Ratings on p.ProductId equals r.ProductId into ratings
select new ProductRating
{
ProductId = p.ProductId,
ProductName = p.ProductName,
Total = ratings.Average(r => (double?)r.UserRating) ?? 0
}).ToList();
You have to start with the Product. Also, the order of your joins in your Linq expression is the opposite than in your SQL. And, the group ... by ... needs just rt.UserRating as the value selector
var con = (from d in db.Products
join c in db.Ratings on d.ProductId equals c.ProductId into ps
from rt in ps.DefaultIfEmpty()
group new { rt.UserRating } by new { d.ProductId, d.ProductName } into g
select new ProductRating
{
ProductId = g.Key.ProductId,
ProductName = g.Key.ProductName,
Total = g.Sum(r => r.UserRating) / g.Count()
})
.ToList();
Also, this would break if g.Count() is zero. But you have a few choices anyways:
Add more complexity to the query and pray for EF to be able to translate it into SQL
select new ProductRating
{
ProductName = g.Key.ProductName,
Total = g.Count() > 0 ? (g.Sum(r => r.UserRating) / g.Count()) : 0
}
Redefine ProductRating or use a helper DTO, so that it takes Sum and Count properties (calculate the average on-demand, let's say, you can still have a Total property)
select new ProductRating
{
ProductName = g.Key.ProductName,
SumRating = g.Sum(r => r.UserRating),
CountRating = g.Count()
}
Your LINQ statement has an inner join, whereas your SQL has a left join.
Related
Linq left outer join doesn't work while matching sql does [duplicate]
How to perform left outer join in C# LINQ to objects without using join-on-equals-into clauses? Is there any way to do that with where clause? Correct problem: For inner join is easy and I have a solution like this 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}) but for left outer join I need a solution. Mine is something like this but it's not working 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 }) where JoinPair is a class: public class JoinPair { long leftId; long rightId; }
As stated in "Perform left outer joins": var q = from c in categories join pt in products on c.Category equals pt.Category into ps_jointable from p in ps_jointable.DefaultIfEmpty() select new { Category = c, ProductName = p == null ? "(No products)" : p.ProductName };
If a database driven LINQ provider is used, a significantly more readable left outer join can be written as such: from c in categories from p in products.Where(c == p.Category).DefaultIfEmpty() If you omit the DefaultIfEmpty() you will have an inner join. Take the accepted answer: from c in categories join p in products on c equals p.Category into ps from p in ps.DefaultIfEmpty() This syntax is very confusing, and it's not clear how it works when you want to left join MULTIPLE tables. Note It should be noted that from alias in Repo.whatever.Where(condition).DefaultIfEmpty() is the same as an outer-apply/left-join-lateral, which any (decent) database-optimizer is perfectly capable of translating into a left join, as long as you don't introduce per-row-values (aka an actual outer apply). Don't do this in Linq-2-Objects (because there's no DB-optimizer when you use Linq-to-Objects). Detailed Example 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(); When used with LINQ 2 SQL it will translate nicely to the following very legible SQL query: 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 Edit: See also " Convert SQL Server query to Linq query " for a more complex example. Also, If you're doing it in Linq-2-Objects (instead of Linq-2-SQL), you should do it the old-fashioned way (because LINQ to SQL translates this correctly to join operations, but over objects this method forces a full scan, and doesn't take advantage of index searches, whyever...): 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 } );
Using lambda expression 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 });
Now as an extension method: 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 like you would normally use join: var contents = list.LeftOuterJoin(list2, l => l.country, r => r.name, (l, r) => new { count = l.Count(), l.country, l.reason, r.people }) Hope this saves you some time.
Take a look at this example. This query should work: 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 };
An implementation of left outer join by extension methods could look like 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)); } } The resultselector then has to take care of the null elements. 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)); }
take look at this example 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: now you are able to include elements from the left even if that element has no matches in the right, in our case we retrived Arlene even he has no matching in the right here is the reference How to: Perform Left Outer Joins (C# Programming Guide)
This is the general form (as already provided in other answers) 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 }; However here's an explanation that I hope will clarify what this actually means! join b in beta on b.field1 equals a.field1 into b_temp essentially creates a separate result set b_temp that effectively includes null 'rows' for entries on the right hand side (entries in 'b'). Then the next line: from b_value in b_temp.DefaultIfEmpty() ..iterates over that result set, setting the default null value for the 'row' on the right hand side, and setting the result of the right hand side row join to the value of 'b_value' (i.e. the value that's on the right hand side,if there's a matching record, or 'null' if there isn't). Now, if the right hand side is the result of a separate LINQ query, it will consist of anonymous types, which can only either be 'something' or 'null'. If it's an enumerable however (e.g. a List - where MyObjectB is a class with 2 fields), then it's possible to be specific about what default 'null' values are used for its properties: 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 }; This ensures that 'b' itself isn't null (but its properties can be null, using the default null values that you've specified), and this allows you to check properties of b_value without getting a null reference exception for b_value. Note that for a nullable DateTime, a type of (DateTime?) i.e. 'nullable DateTime' must be specified as the 'Type' of the null in the specification for the 'DefaultIfEmpty' (this will also apply to types that are not 'natively' nullable e.g double, float). You can perform multiple left outer joins by simply chaining the above syntax.
Here's an example if you need to join more than 2 tables: 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://stackoverflow.com/a/17142392/2343
Here is a fairly easy to understand version using method syntax: 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 }));
Extension method that works like left join with Join syntax 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())); } } just wrote it in .NET core and it seems to be working as expected. Small test: 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)}
I would like to add that if you get the MoreLinq extension there is now support for both homogenous and heterogeneous left joins now http://morelinq.github.io/2.8/ref/api/html/Overload_MoreLinq_MoreEnumerable_LeftJoin.htm example: //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 EDIT: In retrospect this may work, but it converts the IQueryable to an IEnumerable as morelinq does not convert the query to SQL. You can instead use a GroupJoin as described here: https://stackoverflow.com/a/24273804/4251433 This will ensure that it stays as an IQueryable in case you need to do further logical operations on it later.
There are three tables: persons, schools and persons_schools, which connects persons to the schools they study in. A reference to the person with id=6 is absent in the table persons_schools. However the person with id=6 is presented in the result lef-joined grid. 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); }
Easy way is to use Let keyword. This works for me. from AItem in Db.A Let BItem = Db.B.Where(x => x.id == AItem.id ).FirstOrDefault() Where SomeCondition Select new YourViewModel { X1 = AItem.a, X2 = AItem.b, X3 = BItem.c } This is a simulation of Left Join. If each item in B table not match to A item , BItem return null
This is a SQL syntax compare to LINQ syntax for inner and left outer joins. Left Outer Join: http://www.ozkary.com/2011/07/linq-to-entity-inner-and-left-joins.html "The following example does a group join between product and category. This is essentially the left join. The into expression returns data even if the category table is empty. To access the properties of the category table, we must now select from the enumerable result by adding the from cl in catList.DefaultIfEmpty() statement.
As per my answer to a similar question, here: Linq to SQL left outer join using Lambda syntax and joining on 2 columns (composite join key) Get the code here, or clone my github repo, and play! Query: var petOwners = from person in People join pet in Pets on new { person.Id, person.Age, } equals new { pet.Id, Age = pet.Age * 2, // owner is twice age of pet } into pets from pet in pets.DefaultIfEmpty() select new PetOwner { Person = person, Pet = pet, }; Lambda: var petOwners = People.GroupJoin( Pets, person => new { person.Id, person.Age }, pet => new { pet.Id, Age = pet.Age * 2 }, (person, pet) => new { Person = person, Pets = pet, }).SelectMany( pet => pet.Pets.DefaultIfEmpty(), (people, pet) => new { people.Person, Pet = pet, });
This is the LeftJoin implementation I use. Notice that the the resultSelector expression accepts 2 parameters: one instance from both sides of the join. In most other implementations that I've seen the result selector only accepts one parameter, which is a "join model" with a left/right or outer/inner property. I like this implementation better because it has the same method signature as the built-in Join method. It also works with IQueryables and EF. var results = DbContext.Categories .LeftJoin( DbContext.Products, c => c.Id, p => p.CategoryId, (c, p) => new { Category = c, ProductName = p == null ? "(No Products)" : p.ProductName }) .ToList(); public static class QueryableExtensions { public static IQueryable<TResult> LeftJoin<TOuter, TInner, TKey, TResult>( this IQueryable<TOuter> outer, IEnumerable<TInner> inner, Expression<Func<TOuter, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<TOuter, TInner, TResult>> resultSelector) { var query = outer .GroupJoin(inner, outerKeySelector, innerKeySelector, (o, i) => new { o, i }) .SelectMany(o => o.i.DefaultIfEmpty(), (x, i) => new { x.o, i }); return ApplySelector(query, x => x.o, x => x.i, resultSelector); } private static IQueryable<TResult> ApplySelector<TSource, TOuter, TInner, TResult>( IQueryable<TSource> source, Expression<Func<TSource, TOuter>> outerProperty, Expression<Func<TSource, TInner>> innerProperty, Expression<Func<TOuter, TInner, TResult>> resultSelector) { var p = Expression.Parameter(typeof(TSource), $"param_{Guid.NewGuid()}".Replace("-", string.Empty)); Expression body = resultSelector?.Body .ReplaceParameter(resultSelector.Parameters[0], outerProperty.Body.ReplaceParameter(outerProperty.Parameters[0], p)) .ReplaceParameter(resultSelector.Parameters[1], innerProperty.Body.ReplaceParameter(innerProperty.Parameters[0], p)); var selector = Expression.Lambda<Func<TSource, TResult>>(body, p); return source.Select(selector); } } public static class ExpressionExtensions { public static Expression ReplaceParameter(this Expression source, ParameterExpression toReplace, Expression newExpression) => new ReplaceParameterExpressionVisitor(toReplace, newExpression).Visit(source); } public class ReplaceParameterExpressionVisitor : ExpressionVisitor { public ReplaceParameterExpressionVisitor(ParameterExpression toReplace, Expression replacement) { this.ToReplace = toReplace; this.Replacement = replacement; } public ParameterExpression ToReplace { get; } public Expression Replacement { get; } protected override Expression VisitParameter(ParameterExpression node) => (node == ToReplace) ? Replacement : base.VisitParameter(node); }
Perform left outer joins in linq C# // Perform left outer joins 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/
Here's a version of the extension method solution using IQueryable instead of IEnumerable public class OuterJoinResult<TLeft, TRight> { public TLeft LeftValue { get; set; } public TRight RightValue { get; set; } } public static IQueryable<TResult> LeftOuterJoin<TLeft, TRight, TKey, TResult>(this IQueryable<TLeft> left, IQueryable<TRight> right, Expression<Func<TLeft, TKey>> leftKey, Expression<Func<TRight, TKey>> rightKey, Expression<Func<OuterJoinResult<TLeft, TRight>, TResult>> result) { return left.GroupJoin(right, leftKey, rightKey, (l, r) => new { l, r }) .SelectMany(o => o.r.DefaultIfEmpty(), (l, r) => new OuterJoinResult<TLeft, TRight> { LeftValue = l.l, RightValue = r }) .Select(result); }
If you need to join and filter on something, that can be done outside of the join. Filter can be done after creating the collection. In this case if I do this in the join condition I reduce the rows that are returned. Ternary condition is used (= n == null ? "__" : n.MonDayNote,) If the object is null (so no match), then return what is after the ?. __, in this case. Else, return what is after the :, n.MonDayNote. Thanks to the other contributors that is where I started with my own issue. 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);
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
Overview: In this code snippet, I demonstrate how to group by ID where Table1 and Table2 have a one to many relationship. I group on Id, Field1, and Field2. The subquery is helpful, if a third Table lookup is required and it would have required a left join relationship. I show a left join grouping and a subquery linq. The results are equivalent. class MyView { public integer Id {get,set}; public String Field1 {get;set;} public String Field2 {get;set;} public String SubQueryName {get;set;} } IList<MyView> list = await (from ci in _dbContext.Table1 join cii in _dbContext.Table2 on ci.Id equals cii.Id where ci.Field1 == criterion group new { ci.Id } by new { ci.Id, cii.Field1, ci.Field2} into pg select new MyView { Id = pg.Key.Id, Field1 = pg.Key.Field1, Field2 = pg.Key.Field2, SubQueryName= (from chv in _dbContext.Table3 where chv.Id==pg.Key.Id select chv.Field1).FirstOrDefault() }).ToListAsync<MyView>(); Compared to using a Left Join and Group new IList<MyView> list = await (from ci in _dbContext.Table1 join cii in _dbContext.Table2 on ci.Id equals cii.Id join chv in _dbContext.Table3 on cii.Id equals chv.Id into lf_chv from chv in lf_chv.DefaultIfEmpty() where ci.Field1 == criterion group new { ci.Id } by new { ci.Id, cii.Field1, ci.Field2, chv.FieldValue} into pg select new MyView { Id = pg.Key.Id, Field1 = pg.Key.Field1, Field2 = pg.Key.Field2, SubQueryName=pg.Key.FieldValue }).ToListAsync<MyView>();
This is the prettiest solution I use, give it a try! 😉 (from c in categories let product = products.Where(d=> d.Category == c.Category).FirstOrDefault() select new { Category = c, ProductName = p == null ? "(No products)" : product.ProductName };
(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 });
EF Core LINQ use scalar function
I use Entity Framework Core 2.1. I have a scalar function in the database which adds specified number of days. I created an extension method to execute it: public static class AdventureWorks2012ContextExt { public static DateTime? ExecFn_AddDayPeriod(this AdventureWorks2012Context db, DateTime dateTime, int days, string periodName) { var sql = $"set #result = dbo.[fn_AddDayPeriod]('{dateTime.ToString("yyyy-MM-dd HH:mm:ss.fff")}', {days}, '{periodName}')"; var output = new SqlParameter { ParameterName = #"result", DbType = DbType.DateTime, Size = 16, Direction = ParameterDirection.Output }; var result = db.Database.ExecuteSqlCommand(sql, output); return output.Value as DateTime?; } } I try to use a scalar function in the query (to simplify things I use AdventureWorks2012) as follows: var persons = (from p in db.Person join pa in db.Address on p.BusinessEntityId equals pa.AddressId where p.ModifiedDate > db.ExecFn_AddDayPeriod(pa.ModifiedDate, 100, "DayPeriod_day") select p).ToList(); But get an System.InvalidOperationException: 'A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.' How can I achieve this? UPDATE: I managed to do it with the help of Ivan's answer: var persons = (from p in db.Person join bea in db.BusinessEntityAddress on p.BusinessEntityId equals bea.BusinessEntityId join a in db.Address on bea.AddressId equals a.AddressId where p.ModifiedDate > AdventureWorks2012ContextFunctions.AddDayPeriod(a.ModifiedDate, 100, "DayPeriod_day") select p).ToList(); But now I need to update ModifiedDate for filtered persons. So I'm doing like this: var persons = (from p in db.Person join bea in db.BusinessEntityAddress on p.BusinessEntityId equals bea.BusinessEntityId join a in db.Address on bea.AddressId equals a.AddressId let date = AdventureWorks2012ContextFunctions.AddDayPeriod(a.ModifiedDate, 100, "DayPeriod_day") where p.ModifiedDate > date select new { Person = p, NewDate = date }).ToList(); foreach (var p in persons) p.Person.ModifiedDate = p.NewDate ?? DateTime.Now; db.SaveChanges(); But got System.NotSupportedException: 'Specified method is not supported.' How can I use scalar function in select statement? I tried to split the query by two parts: var filteredPersons = // ok (from p in db.Person join bea in db.BusinessEntityAddress on p.BusinessEntityId equals bea.BusinessEntityId join a in db.Address on bea.AddressId equals a.AddressId where p.ModifiedDate > AdventureWorks2012ContextFunctions.AddDayPeriod(a.ModifiedDate, 100, "DayPeriod_day") select new { Person = p, a.ModifiedDate }).ToList(); var persons = // here an exception occurs (from p in filteredPersons select new { Person = p, NewDate = AdventureWorks2012ContextFunctions.AddDayPeriod(p.ModifiedDate, 100, "DayPeriod_day") }).ToList();
Instead of invoking the function client side (which is this particular case happens as part of the client evaluation of the query filter, while the query reading is still in progress), you can use EF Core Database scalar function mapping so it can be used in LINQ queries and translated to SQL. One way to do that is to create a public static method in the derived context class and mark it with DbFunction attribute: public partial class AdventureWorks2012Context { [DbFunction("fn_AddDayPeriod")] public static DateTime? AddDayPeriod(DateTime dateTime, int days, string periodName) => throw new NotSupportedException(); } and use where p.ModifiedDate > AdventureWorks2012Context.AddDayPeriod(pa.ModifiedDate, 100, "DayPeriod_day") Another way is to create a public static method in another class public static class AdventureWorks2012DbFunctions { [DbFunction("fn_AddDayPeriod")] public static DateTime? AddDayPeriod(DateTime dateTime, int days, string periodName) => throw new NotSupportedException(); } but then you'll need to register it with fluent API (which happens automatically for methods defined inside the context derived class): modelBuilder .HasDbFunction(() => AdventureWorks2012DbFunctions.AddDayPeriod(default(DateTime), default(int), default(string))); The usage is the same: where p.ModifiedDate > AdventureWorksDbFunctions.AddDayPeriod(pa.ModifiedDate, 100, "DayPeriod_day")
How to match two Lists with only items that are different in Linq
I have a StudentData class public class StudentData { public int Id { get; set; } public string FirstName { get; set; } public string Surname { get; set; } public int? Bonus { get; set; } public int? Subject1Mark { get; set; } public int? Subject2Mark { get; set; } public int? Subject3Mark{ get; set; } } Each student has a unique Id that identifies him I have a List<StudentData> CurrentData that has data of 1, John, Smith, 10, 50 ,50 ,50 2, Peter, Parker, 10, 60 ,60 ,60 3, Sally, Smart, 10, 70 ,70 ,70 4, Danny, Darko, 20, 80, 80, 80 I then have a List<StudentData> DataToUpdate which only contains the Id and Marks fields. Not the other fields. 1, null, null, null, 50 ,50 ,50 2, null, null, null, 65, 60 ,60 3, null, null, null, 70 ,70 ,70 The Ids of the list are not necessary in the same order If you compare the two lists only Peter Parker's marks have changed in one subject. I want to get the output to return 2, Peter, Parker, 10, 65 ,60 ,60 I want to takeList<StudentData> CurrentData inner join this with List<StudentData> DataToUpdate but only where marks are different So in SQL it want the following SELECT CurrentData.Id, CurrentData.FirstName , CurrentData.Surname, CurrentData.Bonus, DataToUpdate.Subject1Mark, DataToUpdate.Subject2Mark, DataToUpdate.Subject3Mark FROM CurrentData INNER JOIN DataToUpdate ON CurrentData.Id= DataToUpdate.Id AND ( CurrentData.Subject1Mark<> DataToUpdate.Subject1Mark OR CurrentData.Subject2Mark<> DataToUpdate.Subject2Mark OR CurrentData.Subject3Mark<> DataToUpdate.Subject3Mark ) How do I do the above in LINQ? In the Linq select how do I take all properties from CurrentData but include the 3 Subject properties from DataToUpdate in it to give me List<ChangedData>? I could map each and every property but my StudentData has 100 fields and I would prefer to have something like select new StudentData { this=CurrentData, this.Subject1Mark=DataToUpdate.Subject1Mark, this.Subject2Mark=DataToUpdate.Subject2Mark, this.Subject3Mark=DataToUpdate.Subject3Mark, } but I'm not sure how to write this There is an answer in another stackoverflow question which should work but it doesn't. If I implement that solution (I simplify the example for simplicity) var changedData = currentData .Join(dataToUpdate, cd => cd.Id, ld => ld.Id, (cd, ld) => new { cd, ld }) .Select(x => { x.cd.Subject1Mark= x.ld.Subject1Mark; return x.cd; }) ; but the above x.cd.Subject1Mark isn't updated by x.ld.Subject1Mark although I use the answer in the linked stackoverflow question
The structure of LINQ query looks very similar to SQL: var res = from cur in CurrentData join upd in DataToUpdate on upd.Id equals cur.Id where (cur.Subject1Mark != upd.Subject1Mark || cur.Subject2Mark != upd.Subject2Mark || cur.Subject3Mark != upd.Subject3Mark) select new { Current = cur , UpdatedSubject1Mark = upd.Subject1Mark , UpdatedSubject2Mark = upd.Subject2Mark , UpdatedSubject3Mark = upd.Subject3Mark }; The main difference is that filtering out by inequality has moved from the on clause in SQL to a where clause of LINQ.
LINQ EF QUERY (view difference from condition & dynamic)
I need to make a query to filter records, when get distinct records, get these records information by difference conditions. Also I need these to be dynamic(quantity filter in first select) Let me show you an example: I have 2 tables: tblCustomers: id customerName 1 John 2 Philip 3 Steve tblOrders id customerId ordId payment 1 1 100 True 2 1 101 True 3 1 102 False 4 2 101 True 5 2 102 True 6 2 103 False 7 3 101 True My condition is: where (orderId = 101 and orderId = 102) but get all records of this customer that payment = true I mean my condition is different from what I need to see. I want to receive all records with payment=True without care of orderId I must get: john 100 john 101 Philip 101 Philip 102 Clearing: I need two step - first filter customer who has orderId=101&102, in second step i want to show these selected customers' orderId which payment is true. so for example in first step i get john(who has order id =101&102) then show john 100 - john 101 (which payment istrue). consider tblorder.id=1 isn't in first query but I must show in final result. #Raphael direct me to better expression:I want to see all payment true order for the customers that have orders (101 & 102). but orderids may be more than 2 (thanks #Raphael). 2nd problem is: it must be dynamic. Sometimes I have more than 10 orderId that must be checked - sometimes less. I mean my query must be flexible. In SQL Server select command, I can prepare a string variable and use but in linq I can't do it.
From what I understood from your post and the comments, you need all customers, where the orderId is 101 or 102 and the payment is true. You need the where clause with the orderIds to be dynamic so you can change the Ids to be checked against outside of the query. List<int> IDList = new List<int>(); IDList.Add(101); IDList.Add(102); IDList.Add(110); //... var result = from cust in tblCustomers join order in tblOrders on cust.id equals order.customerId where IDList.Contains(order.ordId) && order.payment == true select new { Name = cust.customerName OrderId = order.ordId payment = order.payment //... } With this you can store all orderIds which need to be checked against in a list, which in turn you can edit from your code. EDIT I really haven't found a clean solution to your problem, so I took a detour, which isn't very clean but should work. In my example I created 2 classes, Customer & Order and filled it with your data from above. Then I took my first query and attached a groupBy to it and a where-clause comparing the length of the grouping with the length of the list var result = (from cust in Customers join order in Orders on cust.Id equals order.customerId where IDList.Contains(order.orderId) && order.payment == true select new { Name = cust.Name, OrderId = order.orderId, Payment = order.payment //... }).GroupBy (r => r.Name) .Where (r => r.Count() == IDList.Count()); Output: Name OrderId Payment Philip 101 True Philip 102 True If you want/need it, I can provide you with the whole Linqpad query, so you can see my whole code and what I have done. Speaking of Linqpad: ignore the result.Dump() line. It won't work on visual Studio.
void Main() { List<Customer> customers = new List<Customer> { new Customer { Id = 1, Name = "John" }, new Customer { Id = 2, Name = "Philip" }, new Customer { Id = 3, Name = "Steve" } }; List<Order> orders = new List<Order> { new Order { Id = 1, CustomerId = 1, OrderId = 100, Payment = true }, new Order { Id = 2, CustomerId = 1, OrderId = 101, Payment = true }, new Order { Id = 3, CustomerId = 1, OrderId = 102, Payment = false }, new Order { Id = 4, CustomerId = 2, OrderId = 101, Payment = true }, new Order { Id = 5, CustomerId = 2, OrderId = 102, Payment = true }, new Order { Id = 6, CustomerId = 2, OrderId = 103, Payment = false }, new Order { Id = 7, CustomerId = 3, OrderId = 101, Payment = true } }; List<int> orderIds = new List<int> { 101, 102 }; var customersWithRelevantOrders = from ord in orders group ord by ord.CustomerId into customerOrders where orderIds.All ( i => customerOrders.Select (co => co.OrderId).Contains(i)) select customerOrders.Key; var paymentTrueOrdersForTheseCustomers = from ord in orders join cust in customers on ord.CustomerId equals cust.Id where ord.Payment where customersWithRelevantOrders.Contains(cust.Id) select new { Name = cust.Name, OrderId = ord.OrderId }; } public class Customer { public int Id { get; set; } public string Name { get; set; } } public class Order { public int Id { get; set; } public int CustomerId { get; set; } public int OrderId { get; set; } public bool Payment { get; set; } }
How to perform "complex" join using Linq
I need to join two objects (tables) A and B. For any A there can be zero to many B's. The query needs the return one row per A. The B's I want to order before the join to be able to select the needed row from B's following a certain condition. Say B has a column Type. If there is a Type 1 then that's the B I need, if not: Type 2 must be selected, etc. Now I think about it, I am not sure how I would to this even in T-sql. I think something like this: SELECT A.* FROM A LEFT JOIN ( SELECT * FROM B AS B1 WHERE B1.Type = (SELECT TOP 1 B2.Type FROM B AS B2 WHERE B2.JoinID = B1.JoinID ORDER BY B2.Type ) ) AS B ON B.JoinID = A.JoinID [edit] With the answer of sgtz I've tried to make it work. If have to make an additional step because the field I want to order by is not present. I add this field in step 1, in step 2 I make a selection of the keys and join everything in step 3, but there I receive an error "The type of one of the expressions in the join clause is incorrect. Type inference failed in the call to 'GroupJoin'." on join "join a in adressen1 on new { b.TopRelatieID..." var adressen1 = from a in db.Adres select new { RelatieAdres = a, Sortering = (int)(a.AdresType.Code == codeVestAdres ? 1 : a.AdresType.Code == codePostAdres ? 2 : (100 + (int)a.AdresType.Code.ToCharArray()[0])) }; var adressen2 = from b in adressen1 group b by new { RelatieID = b.RelatieAdres.RelatieID } into p let TopAdresType = p.Min(at => at.Sortering) select new { TopRelatieID = p.Key.RelatieID, TopAdresType }; var q = from k in db.Klants join b in adressen2 on k.RelatieID equals b.TopRelatieID into b_join from b in b_join.DefaultIfEmpty() join a in adressen1 on new { b.TopRelatieID, b.TopAdresType } equals new { a.RelatieAdres.RelatieID, a.Sortering } into a_join from a in a_join.DefaultIfEmpty()
Here's a worked example. I did it two stages. [Test] public void Test333() { List<Order> O; var M = Prepare333Data(out O); var OTop = from o in O group o by new {id=o.id, orderid=o.orderid} into p let topType = p.Min(tt => tt.type) select new Order(p.Key.id, p.Key.orderid, topType); var ljoin = from m in M join t in OTop on m.id equals t.id into ts from u in ts.DefaultIfEmpty() select new {u.id, u.orderid, u.type}; } public class Manufacturer { public Manufacturer(int id, string name) { this.id = id; this.name = name; } public int id { get; set; } public string name { get; set; } } public class Order { public Order(int id, int orderid, int type) { this.orderid = orderid; this.id = id; this.type = type; } public int orderid { get; set; } public int id { get; set; } public int type { get; set; } } private List<Manufacturer> Prepare333Data(out List<Order> O) { var M = new List<Manufacturer>() {new Manufacturer(1, "Abc"), new Manufacturer(2, "Def")}; O = new List<Order>() { new Order(1, 1, 2), new Order(1, 2, 2), new Order(1, 2, 3), new Order(2, 3, 1) , new Order(2, 3, 1) , new Order(2, 3, 2) }; return M; } response to comments: your "new {" creates a new anonymous type. Two anonymous types created by difference processes are said to have the same signature if types are declared in the same order and they have the same type definition (i.e. int matches int, not int matches short). I haven't tested this scenario extensively in LINQ. That's why I worked with real concrete classes, and not anon types within the JOIN portion. There's probably a way to rework it with pure LINQ, but I don't know what that is yet. I'll post you a response if it occurs to me okay. I'd suggest using concrete classes too for now. i.e. instead of *new {* when doing joins, always use *new CLASSNAME(){prop1="abc",prop2="123"* It's a little bit longer, but safer... safer at least until we work out what is going on inside the LINQ internals.
To be meaningful, you should add at least something to query result, not only A.*. Otherwise you'll have a copy of A with some rows possibly duplicated. If I understood the question correctly, this SQL query should work: SELECT DISTINCT A.*, B.Type FROM A LEFT JOIN (SELECT TOP (1) JoinID, Type FROM B ORDER BY Type GROUP BY JoinID, Type ) AS B ON A.JoinID = B.JoinID Translated to LINQ, it is (UPDATED) (from a in As join b in (from b1 in Bs orderby b1.Type group b1 by b1.JoinID into B1 from b11 in B1 group b11 by b11.Type into B11 from b111 in B11 select new { b111.JoinID, b111.Type }).Take(1) on a.JoinID equals b.JoinID into a_b from ab in a_b.DefaultIfEmpty() select new { a_b.JoinID, /*all other a properties*/ a_b.Type }).Distinct() LINQ may not work 100% correct, but you should grab the idea.