Entity Framework – Joins, Group, Sort Order, & Transactions

Table of Contents
Overview
This is a small collection of Entity Framework joins I have seen or written over the past couple of years. The alternative is to build stored procedures or views. But some shops prefer not to give developers this much access, therefore a quick simple work around is to build a join with Entity Framework. Stored Procedure will likely be faster in performance and easier to build/debug when joins become more complex.
Note: .ToList() at the end of an EF statement will format the data to JSON,
Inner Join with a select
var qryResults = from a in db.table1.Where(col => col.Category == CategoryId)
.Where(col => col.title.Contains(searchString))
join b in db.table2 on a.DynoType equals b.Id
select new
{
a.Id,
a.column1,
a.column2,
};
To use a Form Model to return your results – Not Necessary but here it is anyway.
var results = from m in qryResults
select new FormModelName()
{
Id = m.Id,
IsStock = m.IsStock,
HP = m.HP,
MaxHPRPM = m.MaxHPRPM,
TQ = m.TQ,
MaxTQRPM = m.MaxTQRPM,
// RecordDate = m.DateRecorded
};
Inner Join with Multiple Conditions
For multiple conditions, use new {}. SQL you could write a.col1 = b.col1 AND a.col2 = b.col2.
For Entity Framework the SQL Statement would translate to the following:
join b in db.Table_B on new { a.col1, a.col2} equals new { b.col1, b.col2 }
var results = (from a in db.Table_A
join b in db.Table_B on new { a.Column1, a.Column2} equals new { b.Column1, b.Column2 }
where a.Column_4 == 1
where a.Column_5 == 'A'
select new {
b.Column1,
a.Column1,
a.Column2
}).ToList()
Grouping
Joining tables and grouping multiple columns to get a total count. In the example below, a “Contestants” and “VotingHistory” table are joined and grouped by Contestants ID and Name to get a total count of votes from Voting History.
var userData = (from m in db.Contestants
join u in db.VotingHistory on m.ContestId equals u.ContestId
where u.isActive == true
where m.ContestId == 2
group m by new { m.ContestantId } into g
select new { ContestId = g.Key.ContestantId, Title = g.Key.ContestantName, Count = g.Count() }
).ToList();
ContestId Title Count
------------ ----------------- --------
1032 "Contestant 1" 61
1042 "Contestant 3" 43
1099 "Contestant 4" 24
1002 "Contestant 1" 12
(4 row(s) affected)
Grouping multiple columns:
group g by new { m.COL1, m.COL2} into g
Selecting Specific Columns
var results = db.Events.Where(col => col.IsActive == true)
.Select(col => new { col.Id,
col.Title,
col.Description,
col.IsActive,
col.StartDate,
col.EndDate }).ToList();
Selecting Columns With Distinct Values
Adding Distinct() before ToList() will only bring back distinct values.
var results = db.Contestants.Where(col => col.IsActive == true)
.Select(col => new { col.Event }).Distinct().ToList();
Ordering
Following example will return a list of records ordered from newest to the oldest.
var results = db.Events.Where(col => col.IsActive == true).OrderByDescending(col => col.ID)
Or sort from oldest to newest.
var results = db.Events.Where(col => col.IsActive == true).OrderByDescending(col => col.ID)
Selecting Specific Columns
var results = db.Events.Where(col => col.IsActive == true)
.Select(col => new { col.Id,
col.Title,
col.Description,
col.IsActive,
col.StartDate,
col.EndDate }).ToList();
Descending order in a Join Example
Using orderby a.COLUMN_NAME descending OR ascending to sort the result set
var results = db.Events.Where(col => col.IsActive == true)
orderby a.StartDate descending
.Select(col => new { col.Id,
col.Title,
col.Description,
col.IsActive,
col.StartDate,
col.EndDate }).ToList();
Order by DateTime Hour or Minute Only
Using orderby a.COLUMN_NAME.Hour descending OR ascending to sort the result set by the hour. Also can use Minutes or Seconds depending on the application. This can come in handy if the data is for the current date.
var currentDateTime = DateTime.Today;
var results = from a in db.Events
where a.StartDate >= currentDateTime
select new { col.Id,
col.Title,
col.Description,
col.IsActive,
col.StartDate,
col.EndDate })
.OrderBy(c => c.StartDate.Hour).ToList();
Aliases
Example of an alias when joining multiple tables that have duplicate column name. In this case there is a “RequestService” and an “OfferServices” table joined by a “OfferRequestMatch”.
var results = from a in db.Matches
join b in db.Offers on a.OfferId equals b.Id
join c in db.Requests on a.RequestId equals c.Id
where a.IsConnected == true
select new
{
a.Id,
a.DateConnected,
OfferStatus = a.Status,
OfferDetails = b.Details,
RequestStatus = b.Status,
RequestDetails = c.Details
};
Exclude From List in Where Clause
Get a list of Offer Ids from Matches and then exclude them in the Where clause.
var exludeList = db.ClosedAccounts.Where(col => col.Status < 3).Select(col => col.OfferId).ToArray();
var results = db.Offers.Where(col => !excludeList.Contains(col.Id))
.OrderByDescending(col => col.DateCreated).ToList();
Transactions
Transactions allows you to guarantee a sequence of SQL statements are executed before committing the changes. For example, an API action that executes an insert before an update on another table otherwise do not commit the changes.

The transaction can be initiated with Database.BeginTransaction() and Commit() to commit the changes.
The database entity is instantiated with
DatabaseEntities db = new DatabaseEntities()
Using the database object we can declare a variable to begin and commit the transaction.
var dbContextTransaction = db.Database.BeginTransaction()
Example: A method to add a new record in the Status History table and then update another table labeled Support.
public object AddStatus(StatusHistoryModel form)
{
try
{
var currentDateTime = DateTime.Now;
using (DatabaseEntities db = new DatabaseEntities())
{
using (var dbContextTransaction = db.Database.BeginTransaction())
{
StatusHistory newRecord = new StatusHistory();
newRecord.Status = form.Status;
newRecord.Notes = form.Notes;
newRecord.DateCreated = currentDateTime;
newRecord.RecordedBy = form.UserId;
db.StatusHistories.Add(newRecord);
Support supportRecord = db.Supports.Find(form.RecordId);
supportRecord.Status = form.Status;
supportRecord.DateApproved = currentDateTime;
db.SaveChanges();
dbContextTransaction.Commit();
}
return new { msg = "Success" };
}
}
catch (Exception e)
{
return new { msg = e.InnerException };
}
}
Note: The db.SaveChanges() will not execute if the insert or update fails.
You must be logged in to post a comment.