How do you convert an int to a string in Link to EF?
The clr cant imagine casting an int to a string and Entity framework cant figure out what SQL snippet to translate .ToString() into.
So how do you write a linq statement that returns a string instead of an int?
Sadly EF does not know how to convert .ToString(). You must use the embedded function SqlFunctions.StringConvert: http://msdn.microsoft.com/en-us/library/dd466292.aspx
Also there is no overload for int so you must typecast to double :-(
var vendors =
from v in Vendors
select new
{
Code = SqlFunctions.StringConvert((double)v.VendorId)
};
Related
I am writing a translator which converts DSL to multiple programming language (It seems like Apache Thrift).
For example,
// an example DSL
LOG_TYPE: COMMERCE
COMMON_FIELD : session_id
KEY: buy
FIELD: item_id, transaction_id
KEY: add_to_cart
FIELD: item_id
// will be converted to Java
class Commerce {
private String session_id
private String key;
private String item_id;
private String transaction_id
// auto-created setter, getter, helper methods
...
}
It also should be translated into objective-c and javascript.
To implement it, I have to replace string
// 1. create or load code fragments
String variableDeclarationInJava = "private String {$field};";
String variableDeclarationInJavascript = "...";
String variableDeclarationInObjC = "...";
// 2. replace it
variableDeclarationInJava.replace(pattern, fieldName)
...
Replacing code fragment in String is not type safe and frustrating since it does not any information even if there are errors.
So, my question is It is possible to parse String at compile time? like Scala sqltyped library
If it is possible, I would like to know how can I achieve it.
Thanks.
As far, as I understand, it could be. Please take a look at string interpolation. You implement a custom interpolator, (like it was done for quasi quotations or in Slick).
A nice example of the thing you may want to do is here
I use Entity Framework 4.1 Code First. I want to call a stored procedure that has an output parameter and retrieve the value of that output parameter in addition to the strongly typed result set. Its a search function with a signature like this
public IEnumerable<MyType> Search(int maxRows, out int totalRows, string searchTerm) { ... }
I found lots of hints to "Function Imports" but that is not compatible with Code First.
I can call stored procedures using Database.SqlQuery(...) but that does not work with output parameters.
Can I solve that problem using EF4.1 Code First at all?
SqlQuery works with output parameters but you must correctly define SQL query and setup SqlParameters. Try something like:
var outParam = new SqlParameter();
outParam.ParameterName = "TotalRows";
outParam.SqlDbType = SqlDbType.Int;
outParam.ParameterDirection = ParameterDirection.Output;
var data = dbContext.Database.SqlQuery<MyType>("sp_search #SearchTerm, #MaxRows, #TotalRows OUT",
new SqlParameter("SearchTerm", searchTerm),
new SqlParameter("MaxRows", maxRows),
outParam);
var result = data.ToList();
totalRows = (int)outParam.Value;
I have a situation where I'm trying to filter a LINQ select using a derived sub class.
ctx.BaseEntity.OfType<SubClass>() - this works fine.
However I'd like to do this using a string value instead. I've come across a performance barrier when I have lots (>20) Sub Classes and selecting an Entity without using OfType just isn't an option. I have a generic UI that renders from the base class, so I don't know what Class Type will be returned at compile time.
So what I'd like to do is this:
Perform a projected Select where I
return just the SubClassType from
the database
Perform a second select
using this value as the OfType to
only select the relevant related
entity from the database (No mass
unions generated)
int id = 1;
var classType = (from c in ctx.BaseClass.Include("ClassType")
where c.id == id
select new
{
c.ClassType.TypeName
}).First();
BaseClass caseQuery = ctx.BaseClass.OfType<classType.TypeName>()
.Include("ClassType")
.Include("ChildEntity1")
.Include("ChildEntity2")
.Where(x => x.id== id);
But obviously this won't work because OfType requires a Type and not a string.
Any ideas on how I can achieve this?
Update:
As a side note to the original question, it turns out that the moment you project a query that uses a Navigation Property - it builds the monster SQL too, so I've ended up using a stored procedure to populate my ClassType entity from the BaseClass Id.
So I've just got it to work using eSQL, which I'd never used before. I've posted the code here just in case it helps someone. Has anyone else got a more strongly typed solution they can think of?
BaseClass caseQuery = ctx.BaseClass.CreateQuery<BaseClass>("SELECT VALUE c FROM OFTYPE(Entities.[BaseClass],namespace.[" + classType.TypeName + "]) as c")
.Include("ClassType")
.Include("ChildEntity1")
.Include("ChildEntity2")
.Where(x => x.id== id).FirstOrDefault();
To answer the headline question about calling OfType with a string / runtime type, you can do the following:
// Get the type, assuming the derived type is defined in the same assembly
// as the base class and you have the type name as a string
var typeToFilter = typeof(BaseClass)
.Assembly
.GetType("Namespace." + derivedTypeName);
// The use reflection to get the OfType method and call it directly
MethodInfo ofType = typeof(Queryable).GetMethod("OfType");
MethodInfo ofTypeGeneric = method.MakeGenericMethod(new Type[] { typeToFilter });
var result = (IQueryable<Equipment>)generic.Invoke(null, new object[] { equipment });
Combine this with your stored procedure to get the class name and you (should?) avoid the massive join - I don't have table-per-type implementation to play with so I can't test.
I have a class (built by EF from my database) that has a field that is a flag. The field is stored in the database as an int in a column named CategoryEnum. I have an enum that specifies the permissible values of the flag:
[Flags]
public enum RuleCategories
{
None = 0x0000,
ApplicantBased = 0x0001,
LocationBased = 0x0002,
PolicyBased = 0x0004,
PropertyBased = 0x0008
}
When I try to retrieve the objects using LINQ to Entities
var allRules = from r in context.Rules
where ((r.CategoryEnum & (int)categories) != 0)
select r;
I get this error:
Unable to create a constant value of type 'Closure type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
or, if I try to cast the entity value to the enum
var allRules = from r in context.Rules
where (((RuleCategories)r.CategoryEnum & categories) != 0)
select r;
I get a different error:
Unable to cast the type 'System.Int32' to type RuleCategories'. LINQ to Entities only supports casting Entity Data Model primitive types.
How do I select entities based on a flag?
Thanks
I am going to guess and say that you are using the good old EF 3.5. This works without problems with EF 4.0 in VS2010. There is a problem with the 3.5 version, however, and you will have to use a workaround. Cast the categories variable to int before the query, and then use your int variable inside the query itself:
int preCastCategories = (int)categories;
var allRules = from r in context.Rules
where ((r.CategoryEnum & preCastCategories) != 0)
select r;
I use Oracle's specific data provider (11g), not the Microsoft provider that is being discontinued. The thing I've found about ODP.NET is how picky it is with data types. Where JDBC and other ADO providers just convert and make things work, ODP.NET will throw an invalid cast exception unless you get it exactly right.
Consider this code:
String strSQL = "SELECT DOCUMENT_SEQ.NEXTVAL FROM DUAL";
OracleCommand cmd = new OracleCommand(strSQL, conn);
reader = cmd.ExecuteReader();
if (reader != null && reader.Read()) {
Int64 id = reader.GetInt64(0);
return id;
}
Due to ODP.NET's pickiness on conversion, this doesn't work. My usual options are:
1) Retrieve into a Decimal and return it with a cast to an Int64 (I don't like this because Decimal is just overkill, and at least once I remember reading it was deprecated...)
Decimal id = reader.GetDecimal(0);
return (Int64)id;
2) Or cast in the SQL statement to make sure it fits into Int64, like NUMBER(18)
String strSQL = "SELECT CAST(DOCUMENT_SEQ.NEXTVAL AS NUMBER(18)) FROM DUAL";
I do (2), because I feel its just not clean pulling a number into a .NET Decimal when my domain types are Int32 or Int64. Other providers I've used are nice (smart) enough to do the conversion on the fly.
Any suggestions from the ODP.NET gurus?
This will work with your original SQL:
Int64 id = System.Convert.ToInt64(reader.GetValue(0));