I am working with a gridview in C# and I am wondering if there is an effective way to use one data source instead of three. Right now I have an if statement that selects the Data Source based off the value in a dropdownlist, ddlType.
if (ddlType.Text == "Confirmation")
gvMailMergeExport.DataSourceID = "SqlDSConfirmation";
else if (ddlType.Text == "Cancellation")
gvMailMergeExport.DataSourceID = "SqlDSCancellation";
else
gvMailMergeExport.DataSourceID = "SqlDSPreArrival";
Because each Database needs to look at a different column in the same table to decide which data to show.
The three columns being used are ConfirmationEmail, CancellationEmail, and PreArrivalEmail.
Each of these three columns is a bit value and I only display the rows where the correct column has a '0' for it's value.
So question: is there anything like #ColumnName = 0 that would work for this?
Thank you.
I've never used SQLDataSources, but if you want to go the more custom route, you could build out your query (or use LINQ to SQL or LINQ to Entity Framework) with the custom where clause based on the user selection.
Which technology are you more familiar with? LINQ would be better, but I can give an answer in ADO.NET as well (SqlConnection, SqlCommand, etc).
So the LINQ would be relatively simple. After setting up your LINQ to Entities (EDMX) or LINQ to SQL (DBML) (I'd do the EDMX, because L2S is no longer supported in forward maintenance by MSFT). With an existing DB, it's very easy, drag and drop.
The code would look like this:
using(var context = new LinqDbContext())
{
var results = context.Tablename;
if(limitByConfEmail)
{
results = results.Where(data => data.ConfirmationEmail == true);
}
// do your elses here
gridview.DataSource = results;
gridview.DataBind();
}
Related
I have the following structure that I wan't to query using Linq, specifically Linq to Entities (Enitity Framework).
Table1: RouteMeta
Table2: SitePage
Multiple SitePages can link to the same RouteMeta.
I'm querying the Route Meta to select a number of rows. I'm using a generic repository, currently like this:
return r.Find().ToList();
There's nothing special about it - the Find method accepts an optional linq expression, so I could do something like this:
return r.Find(x => x.Status=1).ToList();
However, what I actually want to do is to select rows from RouteMeta where at least one linked row exists in SitePages with a property IsPublished = true.
return r.Find(x => x.SitePages("where y => y.IsPublished = true");
Obviously, the above isn't correct, I'm just trying to explain the scenario better.
Any advice appreciated.
try something like
return r.Find(x=>x.Sitepages.Any(y=>y.Published))?
I'd also suggesting using a profiler if possible to check that this translates properly into SQL. It probably should do but it depends on how your repository works.
I have written a code which looks like this:
using(var ctx = new myentitiesContext())
{
var currentLoggedUser = ctx.Users.FirstOrDefault(x=>x.Email==User.Identity.Name);
var items = ctx.Items.Where(x=>x.Sales>0 && x.UserId==currentLoggedUser.UserId).ToList();
}
As you can see it's a simple select from the DB. But the tricky part is that sometimes I can select a large quantity of data (50-100k records at a time). So what I've been wondering, are there any ways to tweak the LINQ to perform faster when the data is being pulled out of the table?
I've already created indexes in my table on FK UserId, so that part is done.
My question here is, is there any way to speed up LINQ queries via some tweaks in context configuration section, or perhaps by creating compiled queries, or via some other method ?
P.S. guys, would something like this work good:
ctx.Configuration.AutoDetectChangesEnabled = false;
// my queries...
ctx.Configuration.AutoDetectChangesEnabled = true;
In addition with the things that the rest of the users have written. You could disable lazy loading. That way if the Items Db Table has references to other tables they will not get loaded along with the Items unless you absolutely need it. Check these links
thecodegarden
mehdi
One more think that i would recommend is that you must log the sql queries that your linq expressions create and try to optimise them with your DBA. You could do this by adding an Action<string> delegate on the DbContext.Database.Log that will emit everything between a connection.Open() and a connection.Close(). You could also take the sql query out of your IQueryableor IQueryable<T> calling the .ToString() method on your IQueryable variable.
You should make projection first. For example, this:
var items = ctx.Items.Where(x=>x.Sales>0 && x.UserId==currentLoggedUser.UserId).ToList();
will be better if you write it like this:
var items = ctx.Items.Where(x.UserId==currentLoggedUser.UserId).Where(x2=>x2.Sales>0 ).ToList();
And if you don't need all the object you have to use the "Select" clause before the "Where" and project just the properties that you need to minimize the cost, like this:
ctx.Items.Select(e=>new {e.UserID,e.Sales}).Where(x.UserId==currentLoggedUser.UserId).Where(x2=>x2.Sales>0 ).ToList();
I have a setup on SQL Server 2008. I've got three tables. One has a string identifier as a primary key. The second table holds indices into an attribute table. The third simply holds foreign keys into both tables- so that the attributes themselves aren't held in the first table but are instead referred to. Apparently this is common in database normalization, although it is still insane because I know that, since the key is a string, it would take a maximum of 1 attribute per 30 first table room entries to yield a space benefit, let alone the time and complexity problems.
How can I write a LINQ to SQL query to only return values from the first table, such that they hold only specific attributes, as defined in the list in the second table? I attempted to use a Join or GroupJoin, but apparently SQL Server 2008 cannot use a Tuple as the return value.
"I attempted to use a Join or
GroupJoin, but apparently SQL Server
2008 cannot use a Tuple as the return
value".
You can use anonymous types instead of Tuples which are supported by Linq2SQL.
IE:
from x in source group x by new {x.Field1, x.Field2}
I'm not quite clear what you're asking for. Some code might help. Are you looking for something like this?
var q = from i in ctx.Items
select new
{
i.ItemId,
i.ItemTitle,
Attributes = from map in i.AttributeMaps
select map.Attribute
};
I use this page all the time for figuring out complex linq queries when I know the sql approach I want to use.
VB http://msdn.microsoft.com/en-us/vbasic/bb688085
C# http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx
If you know how to write the sql query to get the data you want then this will show you how to get the same result translating it into linq syntax.
How do you get a list of all the tables and use that list to enumerate the columns?
I've found posts that describe one or the other, but not both.
My net-result is I want to generate a static class which contains names of all the columns in each tables so I could, for example, do:
comboBoxFoo.DisplayMember = SomeNamespace.SomeTable.SomeDisplayColumnName;
comboBoxFoo.ValueMember = SomeNamespace.SomeTable.SomeIDColumnName;
comboBoxFoo.DataSource = dingo;
I'm currently using this method which while it works, it means I have to manually create my tables in a list.
I have a seperate command line project which generates the SomeNameSpace.SomeTable class manually and I add the generated class file in to the project.
Ideally, if I could loop through via a foreach of tables and do something like this:
foreach(var table in someTableNumerationMethodForAGivenContext())
{
var columnList = databaseContext.ColumnNames<someTable>();
foreach(var columnData in columnList)
{
DoJazz(columnData.Name);
}
}
Is there a better way to do this other than manually have to do the databaseContext.ColumnNames() ?
Edit 1:
We're using LinqToSQL. Moving to ADO.NET also an option on the table, but at the moment we have no pressing need to.
Edit 2:
I know L2S does databinding but what I'm after is getting a list of column names as strings from a table. L2S doesn't offer this or it's not apparent on my side.
I'd like to do something like: SomeTable.SomeColumn.ToString() or something. SubSonic has this.
Final:
Thanks everyone. all are very good answers and lead me to the answer. You guys rock!
Nazadus,
Is this what you are looking for?
LINQ to SQL Trick: Get all Table [and Column] Names:
http://blogs.msdn.com/jomo_fisher/archive/2007/07/30/linq-to-sql-trick-get-all-table-names.aspx
What you are describing is essentially an ORM
Linq to SQL is an ORM that will create prototype c# classes for you that contain the information you are describing. It has excellent support for the kind of data binding that you have illustrated.
I think you are looking for this.
DataContext.Mapping.GetTable(yourTable).RowType.DataMemebers()
I can think of two ways to do this.
A) Use SMO to get all the tables / columns in a database. You need to reference:
Microsoft.SqlServer.ConnectionInfo
Microsoft.SqlServer.Management.Sdk.Sfc
Microsoft.SqlServer.Smo
Then, you can do something like this:
ServerConnection connection = new ServerConnection(".");
Server server = new Server(connection);
Database db = server.Databases["Northwind"];
foreach (Table table in db.Tables)
{
foreach (Column column in table.Columns)
{
Console.WriteLine("Table: {0}, Column: {1}",table.Name,column.Name);
}
}
}
B) Use reflection to reflect over your assembly with the dataclasses generated by Linq to Sql. Anything with a Table attribute is a table, and anything with a Column attribute is a column. Let me know if you need a sample...
I have a ASP.Net page using ADO to query MS access database and as a learning exercise i would like to incorporate LINQ. I have one simple table called Quotes.
The fields are: QuoteID, QuoteDescription, QuoteAuthor, QuoteDate. I would like to run simple queries like, "Give me all quotes after 1995".
How would i incorporate LINQ into this ASP.Net site (C#)
Basically, my question is does LINQ work for MS Access ??
LINQ to SQL doesn't support Access (that is, there's no Access/Jet provider for LINQ), but you can query a DataSet with LINQ. This means that you fill your DataSet with any possible data from your database that you might need in your results, and then you filter on the client side. After you have a typed DataSet, and you Fill() it with a TableAdapter, you do something like this:
var year = 1995; // you can pass the year into a method so you can filter on any year
var results = from row in dsQuotes
where row.QuoteDate > year
select row;
You'll have to decide whether this is worth it. You'd have to fill your DataSet with all the quotes, then use LINQ to filter on just those quotes that are after 1995. For a small amount of data, sure, why not? But for a very large amount of data, you'll need to make sure it won't be too slow.
If you're using a DataSet, though, you can write custom queries that become new TableAdapter methods. So you can put the correct SQL for your query in a FillByYear() method in your TableAdapter and use that to fill your typed DataTable. That way you're only getting back the data you need.
If you go this route, remember that Access/Jet uses positional parameters, not named parameters. So instead of
SELECT * FROM Quotes WHERE Year(QuoteDate) > #Year
you'd use something like this:
SELECT * FROM Quotes WHERE Year(QuoteDate) > ?
I don't think LINQ to SQL supports Access. However, if your table is sufficiently small to fit into memory, LINQ to DataSet will let you query datatables etc pretty easily - especially strongly typed datasets.