I have a connection string and I want to use LINQ to query a remote database. In the Microsoft example they use the DataContext class. However the DataContext does not appear in Intellisense. It says that it uses 'System.Data.Linq` but I am not seeing that either. http://msdn.microsoft.com/en-us/library/bb350721(v=vs.110).aspx
Is there a Hello World example for using a connection string and LINQ?
public void SimpleQuery()
{
var connectionString = #"Server=10.1.10.1;database=Mydatabase;uid=myusername;password=mypassword;";
DataContext dc = new DataContext(connectionString);
var q =
from n in dc.table
select n;
Console.WriteLine(n);
}
Well, that is not how it works or at least it is not that simple.
In order to be able to run linq queries against your DB, first you need to map your db tables to dot net classes.
You can do that in various ways, for example you can use Linq to Sql, or Entity framework.
For EF, you need to decide which EF approach you are going to use (Model First,Code First etc.) Then you should configure your settings and create your db context.Take a look at Entity Framework documentation for more details...
Related
I have the following method in a data access class which uses entity framework:
public static IEnumerable<entityType> GetWhere(Func<entityType, bool> wherePredicate)
{
using (DataEntities db = new DataEntities())
{
var query = (wherePredicate != null)
? db.Set<entityType>().Where(wherePredicate).ToList()
: db.Set<entityType>().ToList();
return query;
}
}
This works fine when I use the entities across all layers... however I am trying to move to using a DTO class and I would like to do something like the following:
public static IEnumerable<EntityTypeDTO> GetWhere(Func<EntityTypeDTO, bool> wherePredicate)
{
//call a method here which will convert Func<EntityTypeDTO,bool> to
// Func<EntityType,bool>
using (DataEntities db = new DataEntities())
{
var query = new List<EntityType>();
if (wherePredicate == null)
{
query = db.Set<EntityType>().ToList();
}
else
{
query = (wherePredicate != null)
? db.Set<EntityType>().Where(wherePredicate).AsQueryable<EntityType>().ToList()
: db.Set<EntityType>().ToList();
}
List<EntityTypeDTO> result = new List<EntityTypeDTO>();
foreach(EntityType item in query)
{
result.Add(item.ToDTO());
}
return result;
}
}
Essentially I want a method which will convert Func to Func.
I think I have to break down the Func into an expression tree and then rebuild it somehow in the entityType?
I want to do this to allow the Presentation Layer to just pass the Expression queries?
Am I missing something basic or is there an easier design pattern that can pass a query from a DTO to a data access class without knowing the details of the query?
I have tried making the DTO inherit from the entity which doesn't seem to work either?
If there is a better design pattern that I am missing I would love a pointer and I can investigate from there...
Firstly I would suggest that you put a querying layer of your own in front of Entity Framework rather than allowing any arbitrary Func to be passed in because it will be very easy in the future to pass a Func that Entity Framework can not translate into a SQL statement (it can only translate some expressions - the basics are fine but if your expression calls a C# method, for example, then Entity Framework will probably fail).
So your search layer could have classes that you build up as criteria (eg. a "ContainsName" search class or a "ProductHasId" class) that are then translated into expressions in your search layer. This separates your app entirely from the ORM, which means that ORM details (like the entities or like the limitations of what Funcs can and can't be translated) don't leak out. There's lots out there that's been written about this some of arrangement.
One final note, though, if you are working close to the ORM layer, Entity Framework is very clever and you could probably get a long way without trying to translate your Func<dto, bool> to a Func<entity, bool>. For example, in the below code, accessing "context.Products" returns a "DbSet" and calling Select on it returns an IQueryable and calling Where on that also returns an IQueryable. Entity Framework will translate all of that into a single SQL statement so it won't pull all other Products into memory and then filter the ID on that memory set, it will actually perform the filtering in SQL even though the filter is operating on a projected type (which is equivalent to the DTO in your case) and not the Entity Framework entity -
var results = context.Products
.Select(p => new { ID = p.ProductID, Name = p.ProductName })
.Where(p => p.ID < 10)
.ToList();
The SQL executed is:
SELECT
[Extent1].[ProductID] AS [ProductID],
[Extent1].[ProductName] AS [ProductName]
FROM [dbo].[Products] AS [Extent1]
WHERE [Extent1].[ProductID] < 10
So, if you changed your code to get something like..
return context.Products
.Map<Product, ProductDTO()>()
.Where(productDtoWherePredicate)
.ToList();
.. then you might be just fine with the Funcs that you already have. I presume that you already have some sort of mapping functions to get from EF entities to DTOs (but if not then you might want to look into AutoMapper to help you out - which has support for "projections", which are basically IQueryable maps).
I am going to put this up as an answer.Thanks to Dan for the quick answer. Looking at what you are saying I can write a query/filter set of classes. for example, take the following code:
GetProducts().GetProductsInCategory().GetProductsWithinPriceRange(minPrice, maxPrice);
This code would run like so: Get Products would get all products in the table and the remaining functions would filter the results. if all queries run like this it may put a significant load on the Data Access Layer/ DB Server Connections... not sure.
or
An Alternate I will work on also is:
If each function creates a Linq expression, I could combine them like this: How do I combine multiple linq queries into one results set?
this may allow me to do this in a manner where I can return the filtered results set from the database.
Either way I am marking this as answered. I will update when I have more details.
I don't know much about the mechanics of how ORM tools work, but from working with Entity Framework (EF), I know it's somehow possible to auto-generate CLR classes from arbitrary Views stored in a database. In EF these classes are auto-generated from your entity model. EF can even get column information from a stored procedure and generate a new "complex type" from this information.
How is it possible auto-generate .NET classes, using only (1) the information provided by the SQL SELECT statement and (2) the ability to query the database for its metadata?
Because the SQL is stored in a database, we know at compile time what the SELECT SQL is. Similarly, Entity Framework knows what a View or stored procedure's SELECT SQL is at compile time. We want to auto-generate .NET classes from knowing the SELECT SQL and querying the database's metadata. I need to be able to transform the resulting single DataTable into the auto-generated classes.
It seems like the answer to my question lies in having knowledge of ORM tools;
is there an ORM tool out there that can already do what I need, or
could you explain how Entity Framework auto-generates its .NET classes from Views and Stored Procedures?
Or if you can come up with another solution to auto-generating classes for my scenario, that would also be appreciated.
If any clarification is needed, just let me know.
Metadata about tables and views are loaded from system views: sys.tables, sys.views, sys.columns and others.
Edit:
I just tested how EF gets column names and types and it indeed executes stored procedure and iterates over returned columns. It only uses some complex queries to correctly build call command and handle return value.
You actually don't really need an ORM to do this if you use the System.Data.SqlClient namespace. Here's a quick-and-dirty example that works for random query statements:
public static List<string> GetColumns(string connectionString, string queryString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand(queryString, connection);
connection.Open();
List<string> columnNames = new List<string>();
SqlDataReader reader = adapter.SelectCommand.ExecuteReader();
for (int xx = 0; xx < reader.FieldCount; xx++)
{
columnNames.Add(reader.GetName(xx));
}
return columnNames;
}
}
This doesn't help you auto-generate the classes per se. Still, it's a starting point for pulling the data you'll need for doing so.
I figured out how to do this. I wrote a very basic solution to this here.
In order to acces my db and use my stored procedures I made this very simple data access layer (if someone can call this "layer"). I have 8 files where each file looks like:
using System;
using System.Data;
using System.Data.Common;
using Microsoft.Practices.EnterpriseLibrary.Data;
public class TasksDBHandler
{
private static Database db = DatabaseFactory.CreateDatabase("DBNAME");
public static void SetTaskDepreciationData(long taskId, long fieldId, string value)
{
DbCommand command = db.GetStoredProcCommand("dbo.P_CUS_TSK_SetTaskDepreciationData");
db.AddInParameter(command, "#task_id", DbType.Int64, taskId);
db.AddInParameter(command, "#field_id", DbType.Int64, field);
db.AddInParameter(command, "#value", DbType.String, value);
db.ExecuteNonQuery(command);
}
//Many more stored procedures calls
}
I want to build a new and better data access layer but I don't know how should it look like. I want the ability to use stored procedures without the need to write static method for each stored procedure, I want better connection menagement and so on/
Is anyone have any clue how to do so?
I am using .Net and SQL SERVER.
Have you looked at any of the ORM products out there? There's Linq2Sql, Entity Framework, NHibernate, and others. Unless what you need to do is very basic, you'll probably have better results learning to use an existing framework than trying to write your own.
In an ORM like Entity Framework, you typically don't manage your connection manually, it defines an object (or entity) model from your database and a "context" which is responsible for retrieving the data from your database and mapping it to the correct properties on the classes in your entity model. So you request something from the context, it loads the data necessary to fulfill your request into memory, you work with it like other classes, and then tell the context to save your changes back to the database. There are several ways to interact with your entity model in entity framework, but the example I'll use is Linq2Entities. You write a Linq query, and the context is responsible for turning that into a query against the database *disclaimer: I haven't tried to run this code, it's just meant to serve as an example
using(MyEntitiesContext context = new MyEntitiesContext())
{
var idleUsers = from u in context.User
where u.LoggedIn && u.LastActivity > DateTime.Now.AddMinutes(-30)
select u;
foreach(User u in idleUsers)
{
u.Status = UserStatus.Idle;
}
context.SaveChanges();
}
Obviously there's a lot going on behind the scenes:
There's the whole object model that gets generated from your database (you select the tables you want to be included in your model, and you can create multiple models in the same project).
There's the context, which manages the database connection and turns your Linq expression into a database query
There's the connection string that has to be defined your .config file so Entity Framework knows how to connect to your database
You should be able to find plenty of information on Entity Framework, but the easiest way I've found to learn is to jump in and start trying to do something, and then find answers to questions as they come up. I wouldn't try to use it right away on something highly critical or time sensitive, as there's definitely a learning curve, and you'll learn better ways of working with it once you've experienced some of the pitfalls.
Here's a link to Microsoft's Entity Framework 4 Quickstart which should give you something fairly straightforward to try out. Have fun!
Can anybody help me with next: how can I use two different data contexts in one LINQ request?
using (var db = new DataMapDataContext(Connection))
{
using (var dbAdd = new DataMapDataContext(ConnectionAdd))
{
return (from i in dbAdd.ITEMs
join p in db.U_OTT_PINs on i.ITEMNO equals p.PIN_CODE
where p.PIN_TYPE == Utils.PinItem
select ...
}
}
Is it possible?
UPDATE:
I resolved my issue, but not with different data contexts:
var listPinnedItems = new List<string>();
using (var db = new DataMapDataContext(Connection))
{
listPinnedItems = (from lpi in db.U_OTT_PINs
where lpi.PIN_TYPE == Utils.PinItem
select lpi.PIN_CODE).ToList();
}
using (var dbAdd = new DataMapDataContext(ConnectionAdd))
{
return (from i in dbAdd.ITEMs
where listPinnedItems.Contains(i.ITEMNO)
...
I'm afraid LINQ to SQL is not made for querying across different databases. See below for possible workaround?
http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/3a15002c-704d-49f9-a8cc-0d2bde186e1d
I don't believe so - these two different contexts could be involved in different transactions in the same database, or even talking to completely different database instances. How would it construct SQL to work across the two?
If you could explain what you're trying to do, we may be able to help you more.
It's possible to use two datacontexts, but you can't do database queries across both at the same time. You could however get the data involved in both queries and query the objects using generic linq statements (linq2objects).
This is one of those questions that shouldn't be answered without first asking "What are you trying to achieve?".
Are both datacontexts pointing to the same database or different databases?
If they connect to same database and the only reason why you have two is that you have separated your entities then you can use just one DC to query a table that 'belongs' to another datacontext. Just use GetTable and L2S will resolve the mappings based on class and member attributes.
If they point to different databases on the same server and the login you're connecting to one of the DBs as has rights to read from the second DB you can include the table from one database in a datacontext based on another db by simply adding the database name as a prefix in the .dbml file.
I have mapped the database in the edmx file from the database. Now how do I use linq to make a query?
here is an example of my problem
var Found = from o in ??????
What suppose to go in the question marks. How do I find what suppose to go in the question marks. I have tried many tutorials but that do not tell you exactly how to use Linq.
Well, Entity Framework generates an ObjectContext for you. You should know the name of your ObjectContext class.
Then to query using LINQ you can do something line that
using(var context = new NorthwindContext())
{
var query = from p in context.ProductsSet select p;
// then loop through your query instance.
}
The above example is very simple you should have a look at http://thedatafarm.com/blog/ for better tutorials