I wanted to use linq as so:
MyDBEntities context = new MyDBEntities();
context.MyTable.Where(i => MyMethod(i.column, valueToTest).ToList();
with
public bool MyMethod(Object a, Object b)
but apparently using such a method with isn't possible
so I was hopping I could use the methode in a stored procedure I would be able to call with linq
do you think is it possible ?
Generally it is possible to create C# function and use it in SQL Server (2005 and newer) but it is not so simple - you must use SQL CLR which means separate project for your function, special references, special types, etc. At last you must deploy the assembly to SQL server to be able to use the function in SQL. General documentation also covering how to create custom function:
Creating SQL Server Objects in Managed Code
Once you have your function on SQL server you can use it within stored procedure and you can use it within query. I'm actually not sure if you can import these functions into Linq-to-sql or EF model and use them in Linq-to-sql or Linq-to-entities queries.
Take a look here for a complete sample:
Calling custom methods in LINQ-to-SQL
I hope I understand you correctly.
Let's say that MyTable is a database table that contains the columns Name, and Address
Here's how you would get a value back whether the results contain the specified value you passed.
public void SomeMethod()
{
MyTable table= new MyTable();
bool b= MyMethod(table.Name, "Fred");
if(b)
//Do something
else
//Do something else
}
public bool MyMethod(MyTable a, object value)
{
using(var context= new MyDBEntities())
{
return context.MyTable.Where(i => a == value).Any();
}
}
This is what the database table 'MyTable' looks like behind the scenes.(the data context generated this)
public class MyTable
{
public string Name { get; set; }
public string Address { get; set; }
}
So you can see in the first method I pass table.Name to MyMethod, that's only possible because MyTable has a pubic property called Name. Also notice that we are using type Object for the value, as the parameter could an int, a string, a date time, who knows.
Note: This is untested code, but should get off to right track if I understand you correctly.
Related
I create a simple stored procedure with some joins with the customer table and other related tables, which takes in two parameters. I can execute this SP in SQL and works.
I drag and drop this SP to my DBML file and recompile.
I add the below code in order to call the SP and return it in a List
public IQueryable<Entities.Customer> AllCustomerRanges(int CId, int ItemID)
{
List<Entities.Customer> c = myDataContext.spCustomerRanges(CId, ItemID).ToList();
}
This gives me the error:
Cannot implicitly convert type 'System.Collections.Generic.List< spCustomerRangesResult>' to 'System.Collections.Generic.List< Entities.Customer>'
Now i dont have a class spCustomerRangesResult but after some research I'm puzzled if i have done something wrong or if i need to implement a class with all the properties that the Customer class has (which sounds a little long winded) or if i've just made an error.
Any idea of how i can call a SP which shows the data in a List?
new class spCustomerRangesResult automatically generated based on sp result, you should convert it to Entities.Customer like this:
public IQueryable<Entities.Customer> AllCustomerRanges(int CId, int ItemID)
{
var c = myDataContext.spCustomerRanges(CId, ItemID).ToList();
if (c == null)
return null;
var customers = c.Select(a => new Entities.Customer
{
FirstName=a.spResultFirstName,
LastName = a.spResultLastName
//this just example conversion, change it as needed.
});
return customers;
}
please note, that I return IQueryable even though the approach that you take when using ToList() but yet returning IQuerybale may not be needed. I dont know all details so this only to show how to convert but the whole method may need re-factoring.
`Hi,
Can somebody please give me a pointer on this? I have 8 servers each with 8 databases which look identical exept server/database name. We are talking thousands of tables.
I create my data contexts with sqlmetal.exe
After creating my data contexts, I import them into the application and then I run comparison scripts over the databases to compare results.
My problem is dynamically switching between data contexts.
Datacontext.DAL.DUK1 duk1sdi = new Datacontext.DAL.DUK1(connectionString);
Datacontext.DAL.DUK3 duk3sdi = new Datacontext.DAL.DUK3(connectionString);
string fromOne = runQuery(duk1sdi);
string fromThree = runQuery(duk3sdi);
public static string runQuery(DataContext duk)
{
var query =
from result in duk.TableA
select result.Total;
string returnString = query;
return returnString;
}
I have no problem with the query running when the duk is predefined, however how do I define and pass the datacontext to the function?
The error I get is:
Error 1 'System.Data.Linq.DataContext' does not contain a definition
for 'TableA' and no extension method 'TableA' accepting a first
argument of type 'System.Data.Linq.DataContext' could be found (are
you missing a using directive or an assembly reference?)
You could use the GetTable<T> method, where T is the type of the table, e.g. TableA.
public static string runQuery(DataContext duk) {
var table = duk.GetTable<TableA>();
var query = from result in table select result.Total;
...
}
However, all types of TableA will need to be the same type, strictly (I'm pretty sure).
Otherwise you would need to literally branch the logic for the handling of each context. Since you can extend your DataContext instances (in general, maybe not in your specific case) then you could have them share an interface that exposes a collection property of TableA, but you would need a higher level context wrapper to pass around then - unless you pass around the collection by altering the method signature.
You can use interfaces. Check this answer, but be sure to script the interfaces using a .tt file with the amount of tables you have.
Edit:
If you have generated contexts which you want to use interchangeably in a reusable method, you have the problem that the generated TableA classes are not reusable, since they are different types (even though the names may match, but that doesn't make them equal). Therefore you need to abstract the actual types, and one way to do this, is to use interfaces. You build your reusable method around an interface which abstracts the specific context-type and table-type. The downside is that you have to implement the interfaces on the generated contexts and tabletypes. This though is something you can solve using a .tt script.
Pseudo code:
// Define interface for table
public interface ITableA {
// ... properties
}
// Define interface for context
public interface IMyContext {
IQueryable<ITableA> TableA { get; }
}
// Extend TableA from DUK1
public partial class TableA: ITableA {
}
// Extend DUK1
public partial class Datacontext.DAL.DUK1: IMyContext {
IQueryable<ITableA> IMyContext.TableA {
get { return TableA; }
}
}
// Same for DUK3 and TableA FROM DUK3
// Finally, your code
Datacontext.DAL.DUK1 duk1sdi = new Datacontext.DAL.DUK1(connectionString);
Datacontext.DAL.DUK3 duk3sdi = new Datacontext.DAL.DUK3(connectionString);
string fromOne = runQuery(duk1sdi);
string fromThree = runQuery(duk3sdi);
public static string runQuery(IMyContext duk) {
// Note: method accepts interface, not specific context type
var query = from result in duk.TableA
select result.Total;
string returnString = query;
return returnString;
}
If your schema is identical between databases, why script the dbml for all of them? Just create one context with it's associated classes and dynamically switch out the connection string when instantiating the context.
var duk1sdi = new Datacontext.DAL.DUK1(connectionString1);
var duk3sdi = new Datacontext.DAL.DUK1(connectionString2);
Thanks, guys, I think I found the simplist solution for me based a bit of both your answers and by RTFM (Programming Microsoft Linq in Microsoft .NET Framework 4 by Paulo Pialorsi and Marco Russo)
In this way I don't have to use the large DBML files. It is a shame because I'm going to have to create hundreds of tables in this way, but I can now switch between connection strings on the fly.
First I create the table structure. (outside the program code block)
[Table(Name = "TableA")]
public class TableA
{
[Column] public int result;
}
Then I define the table for use:
Table<TableA> TableA = dc.GetTable<TableA>();
And then I can query from it:
var query =
from result in TableA
select TableA.result;
The goal
I want to call Stored Procedures on my controller with C# + MVC 4 + Entity Framework 5.
The problem
I found this topic that talk about "How to use DbContext.Database.SqlQuery(sql, params) with stored procedure? EF Code First CTP5" and that is exactly what I'm need.
In the topic we have the following code:
context.Database.SqlQuery<myEntityType>(
"mySpName #param1, #param2, #param3",
new SqlParameter("param1", param1),
new SqlParameter("param2", param2),
new SqlParameter("param3", param3)
);
As you can see, there is a generic type (?) called myEntityType and I do not know who is my entity type.
I'm using Entity Framework 5 and all of my CRUD was generated by him.
Details
What I want it is simple (I guess): display the return of procedure in my view. The above's code is what I have on ProductsController:
//
// GET: /Products/
public ActionResult Index()
{
return View(db.bm_products.ToList());
}
I want to display the return in this method.
What I have
Maybe myEntityType is bm_products?
Thanks in advance.
The myEntityType, or TElement, is the type of object that should be created to house the result. If your procedure did this:
SELECT FieldA FROM table
then you'd need a class like this:
public class myEntityType
{
public string FieldA { get; set; }
}
where myEntityType is the class name for the type -that's up to you.
What about myEntityType when you are calling a stored procedure which has two output parameters called #OFirstName and #OLastName both of type varchar in a stored procedure. Those two output parameters are not columns of any table.
I'm trying to implement encrypted columns in EF4 and using the CTP5 features to allow simple use of POCO's to query the database. Sorry that this is a lot of words, but I hope the below gives enough to explain the need and the problem!
So, bit of background, and my progress so far:
The intention is that if you query the tables without using our DAL then the data is rubbish, but I don't want the developers to worry about if/when/how the data is encrypted.
For simplicity, at this stage I'm working on the assumption any string column will be encrypted.
Now, I have successfully implemented this for returning the data using the Objectmaterialized event, and for data commits using the SavingChanges event.
So given the following class:
public class Thing
{
public int ID { get; set; }
[Required]
public string Name { get; set; }
public DateTime Date { get; set; }
public string OtherString { get; set; }
}
The below query returns all the required values and the POCO materialized has clear data in it.
var things = from t in myDbContext.Things
select t;
where myDbContext.Things is a DbSet<Thing>
Likewise, passing an instance of Thing to Things.Add()
(with clear string data in the Name and/or OtherString values)
and then calling myDbContext.SaveChanges() encrypts the strings before it gets to the data store.
Now, the problem I have is in this query:
var things = from t in myDbContext.Things
where t.Name == "Hairbrush"
select t;
This results in the unencrypted value being compared to the encrypted value in the DB. Obviously I don't want to get all the records from the database, materialize them, and then filter the results based on any supplied Where clause... so what I need to do is: intercept that query and rewrite it by encrypting any strings in the Where clause.
So I've looked at:
writing a query provider, but that doesn't seem like the right solution... (is it?)
writing my own IQueryable wrapper for the DbSet which will capture the expression, run over it using an expression tree visitor and then forward the new expression to the DbSet...
Attempts at both have left me somewhat lost! I prefer the second solution i think since it feels a bit neater, and is probably clearer to other developers in future. But I'm happy to go with either or another better option!!
The main thing I am struggling with is when/how the LINQ expression is applied to the object... I think i've got myself a bit confused as to where the expression executes in the IQueryable object thus I'm not sure which method I need to implement in my wrapper to then grab and manipulate the expression being passed in...
I'm sure I'm missing something fairly obvious here and I'm waiting for that light bulb moment... but its not coming!!
Any help will be very gratefully received!
Thought I'd let you know what my final solution was.
In the end I have gone a wrapper class which implements a Where method, but without going to the extent of implementing IQueryable entirely. LINQ will still execute against the class (at least to the extent that I want/need it to) and will call the Where method with the expression from the LINQ.
I then traverse this ExpressionTree and replace my strings with encrypted values before forwarding the new expressiontree to the internal DbSet. and then returning the result.
Its pretty crude, and has its limitation, but works for our particular circumstance without problem.
Thanks,
Ben
you should use the QueryInterceptor attribute, search here in SO or in google and you find examples on how to use it.
a snippet:
[QueryInterceptor("Orders")]
public Expression<Func<Order, bool>> FilterOrders()
{
return o => o.Customer.Name == /* Current principal name. */;
}
// Insures that the user accessing the customer(s) has the appropriate
// rights as defined in the QueryRules object to access the customer
// resource(s).
[QueryInterceptor ("Customers")]
public Expression<Func<Customer, bool>> FilterCustomers()
{
return c => c.Name == /* Current principal name. */ &&
this.CurrentDataSource.QueryRules.Contains(
rule => rule.Name == c.Name &&
rule.CustomerAllowedToQuery == true
);
}
You can use David Fowler's Query Interceptor:
https://github.com/davidfowl/QueryInterceptor
One example of its use:
IQueryable q = ...;
IQueryable modifed = q.InterceptWith(new MyInterceptor());
And on class MyInterceptor:
protected override Expression VisitBinary(BinaryExpression node) {
if (node.NodeType == ExpressionType.Equal) {
// Change == to !=
return Expression.NotEqual(node.Left, node.Right);
}
return base.VisitBinary(node);
}
i like to make my database insert more dynamicly with functions.
Like this:
private void setValues() {
string test = "foo";
string test2 = "bar";
}
private void WriteToDB() {
dc dcOfMyDatabase = new dc();
DBTable myTable = DbTable() {
field1 = test; // values of other function
field2 = test2; // values of other function
}
}
private void doAll() {
setValues();
WriteToDB();
}
Of Course i can do it with parameters in WriteToDB()... But I have so many fields and hope it works with another clean way.
Im sure there is one correct way for a clean developping something like this.
Thanks and regards.
The correct way is indeed to pass parameters to WriteToDB. If the problem is that you have many parameters, wrap them in a containing class, and pass an instance of this class to your writing function.
Also, consider if using an ORM engine (such as LINQ to SQL or NHIbernate) instead of direct database access classes could be helpful for you.
You can promote them to class members or properties:
string test;
private void setValues() {
test = "foo";
}
or:
string test {get; set;}
You should read about Object Oriented design and programming - this will certifiably help you organize your code in a more logical way.
I'm unsure of what you are trying to do here. Your code snippet has some errors in it and would not compile if you tried to run it.
That being said, if you're looking for a mapping from code to DB I would check out Linq To SQL. Here's a short introduction.