I have a sproc in my Linq to SQL (.NET 4.0) designer that returns the default ISingleResult. I wanted it to return something of Type "MyTable", so I made the change in the designer.
So this works:
List<MyTable> return = dataContext.MySproc.ToList();
However, I would rather cast/convert the return from the sproc in code to stay away from the designer. For some reason I can't get the trick of converting ISingleResult from the sproc into List. Can someone help me with the syntax?
Note, if this is easier in EF and someone can point me to HOWTOs using that toolset, I'm all ears.
Thanks.
Just pass your ISingleResult into the constructor of List.
Related
I need to use the SQRT function as part of a where clause in a Linq EF query. I figured I could do this:
var qry = context.MyTable.Where("sqrt(it.field) > 1");
But it returns an error saying "'sqrt' cannot be resolved into a valid type constructor or function., near function, method or type constructor, line 6, column 5."
I had always assumed that linq literally takes what's in the where clause and translates that into a statement that is executed directly in SQL. That doesn't seem to be the case...
Anyone know the work-around?
Thanks
I don't know how you got your answer working against EF. When I tried it with EF4, it wouldn't work for me. I'd get:
LINQ to Entities does not recognize the method 'Double Sqrt(Double)' method, and this method cannot be translated into a store expression.
So after banging my head against this for a while (after all, Math.Pow(double) is supported, and SQRT is available in SQL), I realised that the square root of a value is the same as its power of a half.
So, this solution works fine.
from e in context.MyEntities
let s = Math.Pow(e.MyDouble, 0.5)
select s;
The generated SQL uses POWER instead of SQRT:
SELECT
POWER( CAST( [Extent1].[MyDouble] AS float), cast(0.5 as float(53))) AS [C1]
FROM [dbo].[MyEntities] AS [Extent1]
A simple enough workaround to a daft problem. Hope this helps someone else out.
I'm using Linq Entities and was able to do this:
testEntities entities = new testEntities ();
ObjectQuery<Fees> fees = entities.Fees;
return from f in fees
let s = Math.Sqrt((double)f.FeeAmount)
where s > 1.0
select f ;
When I check the generated SQL, I get
SELECT [t1].[TestTriggerID]
FROM (
SELECT [t0].[TestTriggerID], SQRT(CONVERT(Float,[t0].[TestTriggerID])) AS [value]
FROM [TestTrigger2] AS [t0]
) AS [t1]
WHERE [t1].[value] > #p0
This seems reasonable. I was unable to use the .Where string format to reproduce the same code, but I'm probably missing something obvious.
Check the msdn document.Entity sql doesn't support the sqrt function.
You can use System.Data.Entity.SqlServer.SqlFunctions.SquareRoot as of EF6.
This page from SQL Server 2008 BOL, talks about CLR Stored Procedures and has a section labelled, "Table-Valued Parameters", which talks about how they can be advantageous. That's great - I'd love to use TVPs in my CLR procs, but unfortunately this seems to be the only reference in the universe to such a possibility, and the section doesn't describe what the syntax would be (nor does the further information linked at the end of the paragraph)
Sure, I can easily find descriptions of how to use TVPs from T-SQL procs, or how to do CLR procs in general. But writing a CLR proc that takes a TVP? Nothing. This is all highly unusal since the passing of multi-row data to a stored proc is a popular problem.
This leads me to wonder if the presence of the section on that page is an error. Somebody please tell me it's not and point me to more info/ examples.
[EDIT]
I was about to post this to one of the MS forums too when I came across this, which seems to be the final nail in the coffin. Looks like it can't be done.
I can find a lot more references. However, these are all for passing table-valued parameters to TSQL procedures, so that's of little use.
However, I've come to the conclusion that it's impossible. First, there is the list of mappings between CLR and SQL types. For table types there is no mapping, so the following does not work, for example:
[SqlProcedure]
public static void StoredProcedure(DataTable tvp, out int sum)
{
return 42;
}
and then
CREATE TYPE MyTableType AS TABLE
(
Id INT NOT NULL PRIMARY KEY,
[Count] INT NOT NULL
)
GO
CREATE ASSEMBLY ClrTest FROM '<somePath>'
GO
CREATE PROCEDURE ClrTest
AS EXTERNAL NAME ClrTest.StoredProcedures.StoredProcedure
GO
Whatever type you try (DataTable, DbDataReader, IEnumerable), the CREATE PROCEDURE call keeps generating an error 6552: CREATE PROCEDURE for "ClrTest" failed because T-SQL and CLR types for parameter "#tvp" do not match.
Second, the documentation on the page you linked to says: A user-defined table type cannot be passed as a table-valued parameter to, or be returned from, a managed stored procedure or function executing in the SQL Server process.
I can not seem to find anywhere how to create a user defined table type in C#, but this also seems to be a dead end.
Maybe you can ask your question somewhere on a Microsoft forum. It's still odd that they mention table-valued parameters on the CLR sproc page but never explain how to implement this. If you find any solution, I'd like to know.
You can use a temporary table created and populated before you call the procedure and read the table inside the clr procedure.
The solution is to serialize your tabular data into a Json-formatted string then pass the string into your CLR proc. Within your clr proc or function you would parse the json to an IEnumerable, list, or tabular object. You may then work with the data as you would any other type of tabular data.
I have written some utilities capable of serializing any sql table into a Json formatted string. I would be happy to share them with anyone providing their e-mail address. Phil Factor has written a nice T-SQL Json parser he called parseJson. I have adapted his solution to the clr which performs much faster. Both accept a Json formatted string and produce a table from the string. I also have a variety of Json utilities I employ with both T-SQL and the CLR capable of serializing, parsing, inserting, deleting, and updating Json formatted strings stored in sql columns.
If you use C# (as opposed to VB, which lacks custom iterators) you can write ADO.NET code to invoke ExecuteNonQuery() and run a stored procedure with a SqlDbType.Structured parameter (i.e., a TVP).
The collection passed as the value of the TVP must implement IEnumerable<SqlDataRecord>. Each time this IEnumerable's yield return is executed, a SqlDataRecord “row” is pipelined to the "table" parameter.
See this article for details.
Whilst it looks like passing tables directly to CLR procedures is currently impossible, I got a result, albeit sub optimal by:
defining a TSQL table valued UDT FooTable
defining a TSQL function which takes FooTable as a param and returns XML using FOR XML EXPLICIT
passing the resultant XML to the CLR function/procedure instead of the table itself
Not ideal, but it gets a bit closer.
Do linq2sql expressions always return IQueryable?
Can I return IList if I wanted?
I think this is the way to do it:
IList<SomeType> result = _someCollection.Where(...).ToList();
By returning an IList, you are evaluating the query. The beauty of Linq2Sql is that it translates your expression into a sql query and executes that against the server. By returning an IList, you lose this functionality.
There is nothing stopping you from calling .ToList() on your IQueryable object once you have created your query though.
Hope that helps
I'm trying to get LinqPad use my dbml model so I could analyze a query from my source code. I've set the DataContext to "Custom LINQ to SQL DataContext", and all the necessary settings, unfortunately even with the simplest query I get an error :
QUERY: from m in Linia select m
ERROR: Could not find an implementation of the query pattern for source type 'MyNameSpace.Linia'. 'Select' not found.
Does anybody know how to get this to work? Thx!
Found it! By default, LINQPad pluralizes table properties in the DataContext. I should have used Linias instead of Linia.
Normally if I'm linking an ObjectDataSource to a GridView and I have a TemplateColumn that has an Eval in it and it's Null, I can just put a ".ToString()" it works fine. For some reason, this doesn't work the same when you're using Linq to SQL.
I originally was using XSD files for my DAL with a custom BLL. I tied it to the GridView with an ObjectDataSource. I'm in the middle of swapping out the XSD files with Linq to SQL and everything is working just like the old way except for the columns that can have Null values.
Has anyone run into this before and if so, how do I work around this problem?
Most everything that LINQ returns is of Nullable types. So in your binding expressions you need to use GetValueOrDefault().ToString() or the new "??" null coalescing operator rather than just plain old ToString(). I hope this helps. Check this link out to.
Example:
// this will output the int if not null otherwise an empty string.
<%# (int?)Eval("MyIntegerField") ?? "" %>