Reputation: 1543
I have been looking at making the switch from SQL TableAdapters to Linq using Entity Framework, however some elements are stopping me whilst also driving me mad at the same time.
I have an ASP.NET 4.0 C# VS2010 Project site.
My requirements are as follows:
Based on my requirements, I started to look at Dynamic Linq using the System.Linq.Dynamic namespace. I had some success but largely my queries became over-complicated.
For my requirements, is there any real reason to use Linq and Entity Framework vs standard SQL?
From what I can tell, standard SQL gives me all the control I need with a query language I can understand and control. Linq is a language I am not amazingly familiar with, and doesn't allow me to make all the elements dynamic out of the box like I need to.
Would I be wrong to go back to using SQL stored procs/table adapters for my querying?
One thing I have learnt from my experimenting with Linq is that controlling the properties via the codebehind gives much better control of information, so I can use this data to parse stored procs for data to feed into gridviews.
This is an example of a Linq expression I was working with:
private void FetchData()
{
using (var Context = new ProjectEntities())
{
string Fields = GetDynamicFields();
var Query =
Context.Users
.Join(Context.UserStats, // Table to Join
u => u.msExchMailboxGuid, // Column to Join From
us => us.MailboxGuid, // Column to Join To
(u, us) => new // Declare Columns for the next Join
{
ObjectGuid = u.objectGuid,
msExchMailboxGuid = u.msExchMailboxGuid,
CompanyName = u.CompanyName,
ResellerOU = u.ResellerOU,
DisplayName = u.DisplayName,
MBXServer = u.MBXServer,
MBXSG = u.MBXSG,
MBXDB = u.MBXDB,
MBXWarningLimit = u.MBXWarningLimit,
MBXSendLimit = u.MBXSendLimit,
MBXSendReceiveLimit = u.MBXSendReceiveLimit,
extensionAttribute10 = u.extensionAttribute10,
legacyExchangeDN = u.legacyExchangeDN,
UserPrincipalName = u.UserPrincipalName,
Mail = u.Mail,
lastLogonTimeStamp = u.lastLogonTimestamp,
createTimeStamp = u.createTimeStamp,
modifyTimeStamp = u.modifyTimeStamp,
altRecipient = u.altRecipient,
altRecipientBL = u.altRecipientBL,
DeletedDate = u.DeletedDate,
MailboxGuid = us.MailboxGuid,
Date = us.Date,
AssociatedItemCount = us.AssociatedItemCount,
DeletedItemCount = us.DeletedItemCount,
ItemCount = us.ItemCount,
LastLoggedOnUserAccount = us.LastLoggedOnUserAccount,
LastLogonTime = us.LastLogonTime,
StorageLimitStatus = us.StorageLimitStatus,
TotalDeletedItemSize = us.TotalDeletedItemSize,
TotalItemSize = us.TotalItemSize,
MailboxDatabase = us.MailboxDatabase
})
.Join(Context.TechContacts, // Table to Join
u => u.UserPrincipalName, // Column to Join From
tc => tc.UPN, // Column to Join To
(u, tc) => new // Declare Final Column Names
{
ObjectGuid = u.ObjectGuid,
msExchMailboxGuid = u.msExchMailboxGuid,
CompanyName = u.CompanyName,
ResellerOU = u.ResellerOU,
DisplayName = u.DisplayName,
MBXServer = u.MBXServer,
MBXSG = u.MBXSG,
MBXDB = u.MBXDB,
MBXWarningLimit = u.MBXWarningLimit,
MBXSendLimit = u.MBXSendLimit,
MBXSendReceiveLimit = u.MBXSendReceiveLimit,
extensionAttribute10 = u.extensionAttribute10,
legacyExchangeDN = u.legacyExchangeDN,
UserPrincipalName = u.UserPrincipalName,
Mail = u.Mail,
lastLogonTimeStamp = u.lastLogonTimeStamp,
createTimeStamp = u.createTimeStamp,
modifyTimeStamp = u.modifyTimeStamp,
altRecipient = u.altRecipient,
altRecipientBL = u.altRecipientBL,
DeletedDate = u.DeletedDate,
MailboxGuid = u.MailboxGuid,
Date = u.Date,
AssociatedItemCount = u.AssociatedItemCount,
DeletedItemCount = u.DeletedItemCount,
ItemCount = u.ItemCount,
LastLoggedOnUserAccount = u.LastLoggedOnUserAccount,
LastLogonTime = u.LastLogonTime,
StorageLimitStatus = u.StorageLimitStatus,
TotalDeletedItemSize = u.TotalDeletedItemSize,
TotalItemSize = u.TotalItemSize,
MailboxDatabase = u.MailboxDatabase,
// New Columns from this join
UPN = tc.UPN,
Customer_TechContact = tc.Customer_TechContact,
Customer_TechContactEmail = tc.Customer_TechContactEmail,
Reseller_TechContact = tc.Reseller_TechContact,
Reseller_TechContactEmail = tc.Reseller_TechContact,
Reseller_Name = tc.Reseller_Name
})
.Where(u => true)
.OrderBy(GlobalVars.SortColumn + " " + GlobalVars.SortDirection)
.Select("New(" + Fields + ")");
// Add Extra Filters
if (!(string.IsNullOrWhiteSpace(SearchCompanyNameTextBox.Text)))
{
Query = Query.Where("CompanyName.StartsWith(@0)", SearchCompanyNameTextBox.Text);
}
// Set the Record Count
GlobalVars.TotalRecords = Query.Count();
// Add Paging
Query = Query
.Skip(GlobalVars.Skip)
.Take(GlobalVars.Take);
// GridView Datasource Binding
GridViewMailboxes.DataSource = Query;
GridViewMailboxes.DataBind();
}
}
This is an example of the same thing via a SQL query:
DECLARE @SQLSTATEMENT NVARCHAR(4000);
DECLARE @FieldList varchar(MAX);
DECLARE @OrderBy varchar(100);
DECLARE @OrderDirection varchar(100);
DECLARE @PageSize int;
DECLARE @StartRow int;
SET @FieldList = 'u.UserPrincipalName, u.Mail, us.TotalItemsize, tc.UPN';
SET @OrderBy = 'u.CompanyName';
SET @OrderDirection = 'ASC';
SET @PageSize = 20;
SET @StartRow = 80;
SET @SQLSTATEMENT = '
SELECT TOP(@PageSize) * FROM
(
SELECT ' + @FieldList + '
,row_number() OVER (ORDER BY @OrderBy ' + @OrderDirection + ') AS [row_number]
FROM Users As u
INNER JOIN UserStats as us
ON u.msExchMailboxGuid = us.MailboxGuid
INNER JOIN TechContacts AS tc
ON tc.UPN = u.UserPrincipalName
) AS r
WHERE r.[row_number] > @StartRow '
EXEC sp_executesql @SQLSTATEMENT,
N'@FieldList varchar(MAX), @OrderBy varchar(100), @OrderDirection varchar(100), @PageSize int, @StartRow int',
@FieldList, @OrderBy, @OrderDirection, @PageSize, @StartRow
I appreciate this is kind of an open question, if I could make it clearer I certainly would. However I am struggling to see the benefits of using Linq in my situation considering my requirements. Linq just doesn't seem very good at writing totally dynamic queries, and presumably has to execute SQL at the end anywhere (therefore SQL is faster?).
I've built front end controls that parse all I need into globalvars that I can then use to call the data:
public class GlobalVars
{
public static int TotalRecords = 0;
public static int TotalPages = 0;
public static int CurrentPage = 0;
public static int LowerPage = 0;
public static int UpperPage = 0;
public static int Take = 0;
public static int Skip = 0;
public static string SortColumn = "CompanyName";
public static string SortDirection = "Ascending";
}
Upvotes: 1
Views: 1272
Reputation: 13855
Using stored procedures will always be faster.
Plus im sure you can see, that infact it is much easier to follow what is going on in your SQL code, rather than Linq.
Actually do you mean calling that in an sql statement from your code. Even then it is easier to read. And at the end of the day, they produce the same thing.
Linq is good for querying all ready obtained lists.
For example, you have a list, but you now want objects that match WHERE x = y
, and a new list WHERE x = z
You can do this without requerying the Database.
If you are going to the Database, using sql query is fine. This can then be used by LINQ if necessary to manipulate the list further.
Some people may disagree but its all down to prefence. I personally call them using SQL code statements.
Upvotes: 3