EF4 throws NotSupported exception when it (imho) shouldn't - entity-framework-ctp5

OK, this thing just puzzles me.
I have a table, say Users, with columns UserID, Name, etc. Have an object mapped to it using CTP5. So now I want to test it, and do the following:
List<User> users = new List();
// Some init code here, making say 3 users.
using (UsersDbContext)
{
// insert users
}
So far so good, works fine.
Now I want to see if the records match, so I select the users back using the following code.
using (UsersDbContext dbc = UsersDbContext.GetDbContext())
{
List<Users> usersRead = dbc.Users.Where(x => x.ID >= users[0].ID && x.ID <= users[users.Count - 1].ID).ToList();
}
This throws and exception:
System.NotSupportedException: LINQ to
Entities does not recognize the method
'User get_Item(Int32)' method, and
this method cannot be translated into
a store expression.
EF has difficulties seeing that I'm just asking to return an int in Users[0].ID ?
If I replace a call to users[0].ID with a straight int - works fine.
I get what it's trying to do, but I thought it should be pretty easy to check if the method belongs to .NET or Sql Server ?

You are trying to access an indexer in an EF expression, which doesn't translate to an SQL query. You'll have to move the parameters outside the query like this:
int first = users[0].ID;
int last = users[users.Count - 1].ID;
List<Users> usersRead = dbc.Users.Where(x => x.ID >= first && x.ID <= last).ToList();

Related

System.InvalidOperationException at Dapper

i'm going to use dapper as my ORM in asp .net project.
So the problem is, i'm going to execute my procedure to return get data by Id.
If the Id is not exist, the error appeard like this
Sequence contains no elements
is there any solution to prevent the error by using dapper? because the other solution using entity framework.
here's my code
var SP_Name = "SP_GetSupplierById";
parameters.Add("#Id", Id);
var getSupplierById = connection.QuerySingle<Supplier>(SP_Name,parameters,commandType:CommandType.StoredProcedure);
return getSupplierById;
and here's my procedure
CREATE PROCEDURE SP_GetSupplierById
#Id int
AS
SELECT * from TB_M_Supplier where id = #Id;
RETURN 0
Thanks for your help
QuerySingle asserts that there is exactly one row returned; not zero, not multiple. If zero is acceptable, then you can use QuerySingleOrDefault - and check for the default, which will be null in the case of reference types (classes). QuerySingleOrDefault only asserts that there aren't multiple rows; zero is fine.
So
var getSupplierById = connection.QuerySingleOrDefault<Supplier>(SP_Name,parameters,commandType:CommandType.StoredProcedure);
return getSupplierById; // todo: consider null

Getting Error "No best type found for implicitly-typed array" using LINQ and Entity Framework

var allCategories = _db.Categories;
var result = from c in allCategories
select new[] { c.CategoryID, c.Name, c.SortOrder};
when i use select new {...}; but i get result as object array.
But when i try to use select new[] {...}; i get the following error.
No best type found for implicitly-typed array
Below is my complete Method of Controller.
public ActionResult Index(jQueryDataTableParamModel param=null)
{
if (Request.IsAjaxRequest() && param!=null)
{
var allCategories = _db.Categories;
var result = from c in allCategories
select new[] { c.CategoryID, c.Name, c.SortOrder};
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = allCategories.Count(),
iTotalDisplayRecords = allCategories.Count(),
aaData = result
},
JsonRequestBehavior.AllowGet);
}
return View();
}
If i am doing wrong way please guide me to right path as i am new to ASP.NET MVC.
Update:
I am getting JSON Array like this:
{"sEcho":"1","iTotalRecords":3,"iTotalDisplayRecords":3,"aaData":[{"CategoryID":1,"Name":"Computers","SortOrder":1},{"CategoryID":2,"Name":"Laptops","SortOrder":1},{"CategoryID":3,"Name":"Mobiles","SortOrder":1}]}
where as i want Json Array like this
{"sEcho":"1","iTotalRecords":3,"iTotalDisplayRecords":3,"aaData":[["CategoryID":1,"Name":"Computers","SortOrder":1],["CategoryID":2,"Name":"Laptops","SortOrder":1],["CategoryID":3,"Name":"Mobiles","SortOrder":1]]}
The reason behind this is datatables is not showing data in grid, so i guess this is the reason behind not showing data. As i am getting the array like the second one in PHP and datatables works fine over there.
Update: 2
I Just Tried like this,
select new [] { Convert.ToString(c.CategoryID), c.Name, Convert.ToString(c.SortOrder)};
as everything will become string. but now after this error is gone i am not getting the error relating to converting of string.
LINQ to Entities does not recognize the method 'System.String
ToString(Int32)' method, and this method cannot be translated into a
store expression.
What you want is not valid JSON. You could create it using string concatenation, but it would not be possible to parse it as JSON.
If you want to produce something that is possible to parse as JSON you need to follow the syntax rules.
If you want a collection of keys and values, you use an object:
{"CategoryID":1,"Name":"Computers","SortOrder":1}
If you use an array you only have values, no keys:
[1,"Computers",1]
Ok. After many tries i finally got the result somehow in arrays rather then in objects.
Many Thanks to #Guffa Also as He helped Alot in Fixing my Problem.
He Finally gave the reply
new object[] { c.CategoryID.ToString(), c.Name, c.SortOrder.ToString() }
Which should have solved my problem but for some reason asp.net LINQ is not supporting .ToString() functions and i did got this error.
The array type 'System.Object[]' cannot be initialized in a query result. Consider using 'System.Collections.Generic.List1[System.Object]' instead.
I am not good in ASP.NET MVC specially with Databases and C# so i start back to googeling.
I think i had to call query two times.
first result is converted ToList() ToList i think supports the ToString Function.
var categories = (from category in allCategories
select category).ToList();
Then here when returning Json i wrote the query back again but here i used the Categories from First Query and then .ToString was working.
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = allCategories.Count(),
iTotalDisplayRecords = allCategories.Count(),
aaData = (from category in categories
select new [] {category.CategoryID.ToString(), category.Name, category.SortOrder.ToString()}).ToArray()
},
It gave me the result i wanted but i am not sure if this is the right way. What should be the Professional way or good way to have a secure and quick response controller. As i don't want to make a mess of my Code.

SQL Lite Xamarin : Query

I'm newbie in SQLite.
I would like to query my SQLite database to get multiple rows.
When I add a new item in my local database I call this method Add:
public bool Add<T>(string key, T value)
{
return this.Insert(new SQliteCacheTable(key, this.GetBytes(value))) == 1;
}
_simpleCache.Add("favorite_1", data1);
_simpleCache.Add("favorite_2", data2);
_simpleCache.Add("favorite_3", data2);
Then,
I would like to retrieve from local database all entries where key starts with "favorite_"
to returns all objects in the database which are "favorite" objects.
I'm experienced in Linq, and I would like to do something like this:
IEnumerable<Element> = repository.Find((element) => element.Key.StartWith("favorite_"))
In the SQLiteConnection class there is a method like this:
SQLite.Net.SQLiteConnection.Find<T>(System.Linq.Expressions.Expression<System.Func<T,bool>>)
But I would like the same with in returns a collection IEnumerable<T>.
Can you help me please?
Thank you.
Jool
You have to build your query on the table itself, not the connection:
Assuming:
SQLiteConnection repository;
Then the code would look like:
var favorites = repository.Table<SQliteCacheTable>().Where(item => item.StartsWith("favorite_"));
The favorites variable is of type TableQuery<SQliteCacheTable> though, so it does not yet contain your data. The execution of the actual SQL query will be deferred until you try to access the results (by enumerating with foreach or converting to a list with ToList, for example).
To actually observe what's going on on the database, you can turn on tracing in sqlite-net, by setting repository.Trace = true on your SQLiteConnection object.
Finally, it's worth mentioning that you can also use the C# query syntax on TableQuery<T> objects, if your comfortable with it. So your query could become:
var favorites = from item in repository.Table<SQliteCacheTable>()
where item.StartsWith("favorite_")
select item;

SQL injection concerns

ok i use this route
routes.MapRoute(
"Catalog/Data",
"Catalog/{*data}",
new { controller = "Catalog", action = "Category", data = "" }
);
the Url looks something like http://localhost/Catalog/Computer/Harddrives/internal
Data beening the Computer/Harddrives/internal part
i split it apart and validate the route
here is where my concerns are, atm i do not check for sql injection
i check the route by getting the category from the database using enitity framework
with this function
public Category GetByRoute(string Route)
{
return (from c in XEntity.CategorySet
.Where(c => c.Route == Route)
.Where(c => c.IsEnabled == true)
select c).FirstOrDefault();
}
should i be worried about sql injection with this?
Linq2Sql and the Entity Framework use SQL parameters (except for one edge case) so you'll be fine.
In your case you're actually using Linq over the CategorySet, and linq is executed locally in this case, so it's CategorySet that's touching the database, the where constraints run after (I believe). Again in this case there's no problem.

Best practices re: LINQ To SQL for data access

Part of the web application I'm working on is an area displaying messages from management to 1...n users. I have a DataAccess project that contains the LINQ to SQL classes, and a website project that is the UI. My database looks like this:
User -> MessageDetail <- Message <- MessageCategory
MessageDetail is a join table that also contains an IsRead flag.
The list of messages is grouped by category. I have two nested ListView controls on the page -- One outputs the group name, while a second one nested inside that is bound to MessageDetails and outputs the messages themselves. In the code-behind for the page listing the messages I have the following code:
protected void MessageListDataSource_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
var db = new DataContext();
// parse the input strings from the web form
int categoryIDFilter;
DateTime dateFilter;
string catFilterString = MessagesCategoryFilter.SelectedValue;
string dateFilterString = MessagesDateFilter.SelectedValue;
// TryParse will return default values if parsing is unsuccessful (i.e. if "all" is selected"):
// DateTime.MinValue for dates, 0 for int
DateTime.TryParse(dateFilterString, out dateFilter);
Int32.TryParse(catFilterString, out categoryIDFilter);
bool showRead = MessagesReadFilter.Checked;
var messages =
from detail in db.MessageDetails
where detail.UserID == (int)Session["UserID"]
where detail.Message.IsPublished
where detail.Message.MessageCategoryID == categoryIDFilter || (categoryIDFilter == 0)
where dateFilter == detail.Message.PublishDate.Value.Date || (dateFilter == DateTime.MinValue)
// is unread, showRead filter is on, or message was marked read today
where detail.IsRead == false || showRead || detail.ReadDate.Value.Date == DateTime.Today
orderby detail.Message.PublishDate descending
group detail by detail.Message.MessageCategory into categories
orderby categories.Key.Name
select new
{
MessageCategory = categories.Key,
MessageDetails = categories.Select(d => d)
};
e.Result = messages;
}
This code works, but sticking a huge LINQ statement like this in the code-behind for a LinqDataSource control just doesn't sit right with me.
It seems like I'm still coding queries into the user interface, only now it's LINQ instead of SQL. However, I feel that building another layer between the L2S classes and the UI would cut back on some of the flexibility of LINQ. Isn't the whole point to reduce the amount of code you write to fetch data?
Is there some possible middle ground I'm not seeing, or am I just misunderstanding the way LINQ to SQL is supposed to be used? Advice would be greatly appreciated.
All your LINQ querys should be in a business logic class, no change from older methodologies like ADO.
If you are a purist you should always return List(of T) from your methods in the business class, in fact, the datacontext should only be visible to the business classes.
Then you can manipulate the list in the user interface.
If you are a pragmatist, you can return a IQueryable object and make some manipulations in the user interface.
Regardless of LINQ, I think that mixing presentation code with database-relaed code is not a good idea. I would create a simple DB abstraction layer on top of LINQ queries. In my opinion LINQ is just a convenient tool, that doesn't have a serious impact on traditional application design.

Resources