I am trying to query my entity with a predicate on a DateTimeOffset column, but getting a 500 error response from the Breeze.WebApi. The error message is
Unable to perform operation: leon types:System.Nullable`1[System.DateTimeOffset], System.DateTime
The uri I see produced is something like
http://localhost:49800/api/Breeze Orders?$filter=LocalDateTime%20le%20datetime'2013-03-03T00%3A00%3A00.000Z'
What is working:
I can query on other DateTime, text columns
I can save new data into my 'LocalDateTime' field
The full error response from the query is:
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Unable to perform operation: leon types:System.Nullable`1[System.DateTimeOffset], System.DateTime
</ExceptionMessage>
<ExceptionType>System.Exception</ExceptionType>
<StackTrace>
at Breeze.WebApi.ParseTreeVisitor.CoerceTypes(String operatorName, Expression& leftExpr, Expression& rightExpr) at Breeze.WebApi.ParseTreeVisitor.VisitBinary(ParseTreeNode node, String operatorName, Expression leftExpr, Expression rightExpr) at Breeze.WebApi.ParseTreeVisitor.VisitNode(ParseTreeNode node) at Breeze.WebApi.ParseTreeVisitor.Parse(Type rootType, ParseTreeNode node) at Breeze.WebApi.ExpressionTreeBuilder.Parse(Type rootType, String source) at Breeze.WebApi.ODataActionFilter.BuildFilterFunc(String filterQueryString, Type elementType) at Breeze.WebApi.ODataActionFilter.OnActionExecuted(HttpActionExecutedContext actionExecutedContext) at System.Web.Http.Filters.ActionFilterAttribute.CallOnActionExecuted(HttpActionContext actionContext, HttpResponseMessage response, Exception exception) at System.Web.Http.Filters.ActionFilterAttribute.<>c__DisplayClass2.<System.Web.Http.Filters.IActionFilter.ExecuteActionFilterAsync>b__0(HttpResponseMessage response) at System.Threading.Tasks.TaskHelpersExtensions.<>c__DisplayClass41`2.<Then>b__40(Task`1 t) at System.Threading.Tasks.TaskHelpersExtensions.ThenImpl[TTask,TOuterResult](TTask task, Func`2 continuation, CancellationToken cancellationToken, Boolean runSynchronously)
</StackTrace>
</Error>
.
EDIT
Getting there, but not quite. After installing Breeze 1.2.8 the client is now generating correctly typed uri e.g.
http://localhost:49800/api/Breeze/Orders?$filter=LocalDateTime%20ge%20datetimeoffset'2013-01-01T11%3A00%3A00.000Z'
In my case using setEntityTypeForResourceName to fix the entity type isnt needed. The above uri still gives me the error:
Unable to perform operation: leon types:System.Nullable`1[System.DateTimeOffset], System.DateTimeOffset
Changing my server side model from
public Nullable<System.DateTimeOffset> LocalDateTime { get; set; }
to
public System.DateTimeOffset LocalDateTime { get; set; }
allows my uri to work.
So can we please have a fix for nullable DateTimeOffset.
This is fixed in v 1.2.7. Please post back if you still see the error.
--- Further information ---
There have been several posts since 1.2.7 indicating that this error was still occuring. It turns out that the issue is NOT that breeze doesn't understand 'dataTimeOffsets'. It is that breeze is very forgiving of incorrect EntityType/Resource name mappings in queries except in the case of queries involving 'DateTimeOffsets'. This post is a bit long, so if you just need the fix, read the last paragraph.
The "Unable to perform operation: ... " error occurs when executing a query against a dateTimeOffset property when the resource name declared in the query ( the value in the 'from' clause) cannot be mapped to an existing entityType name (defined in metadata).
If breeze can find an entity type that maps to the resource name declared in the query, it uses the metadata for that entityType to validate the query and create an OData filter string. However, if it can't find a matching entity type, which is a perfectly acceptable condition because some 'resourceName's will not map to entities, it tries to infer the datatypes involved in any query clauses by looking at any constant parameters involved in the query and using their datatype. The problem is that a javascript date object can be mapped to either a .NET 'DateTime' or a 'DateTimeOffset' and Breeze can only pick one and in this case picks the 'wrong' one.
This kind of mismapping does not cause problems when data is returned from a query because breeze only uses the entity type of the query to validate and construct an appropriate OData filter string. Data returned from any query is inspected to determine the entityTypes of each item returned so the resourceName/entityType mapping is not needed. ( A single query may return multiple entity types because of the use of 'expand' or 'select' clauses.)
The root cause of the mapping issue involves the map of resource names to entity types that breeze keeps in each MetadataStore. This mapping is available via the MetadataStore.getEntityTypeNameForResourceName and MetadataStore.setEntityTypeForResourceName methods. When using Entity framework metadata, breeze assumes that Entity Framework 'EntitySet' names correspond to 'resourceNames'. This assumption is what is causing the problem. If you query a 'resourceName' that is different from one of your EntitySet names, Breeze does not know the corresponding 'entity Type' and falls back on inferring the datatypes used in the query, instead of using the 'entity Type' metadata.
There are two fairly simple fixes, either of which work.
1) Use the MetadataStore.setEntityTypeForResourceName method to map your resource names to your entity types. Note that you can have as many resource names as you like mapped to the same entity type.
2) Name your methods ( that correspond to resource names) to the names of the corresponding EntitySet defined in EF and not the name of the type that is returned. A common convention is that EntitySet names ( and hence resource names) are pluralized, whereas EntityType names are usually singular. i.e. 'Customers' is a resource name and 'Customer' is the EntityType
Related
In http://docs.oasis-open.org/odata/odata/v4.0/odata-v4.0-part1-protocol.html
11.2.7 Requesting Entity References
If the resource path terminates on a single entity, the response MUST be the format-specific representation of an entity reference pointing to the related single entity. If the resource path terminates on a single entity and no such entity exists, the service returns 404 Not Found.
11.2.6 Requesting Related Entities
If the relationship terminates on a single entity, the response MUST be the format-specific representation of the related single entity. If no entity is related, the service returns 204 No Content
I think those two cases are similar, they should either both return 404 or 204, why the specification defines the response differently.
The spec makes sense. Think of it in terms of an in-memory dictionary of Entity objects indexed by their identity value, and a routing engine that maps URI paths of the form /Entities(x) to the Entity with identity value x.
private static final Map<int, Entity> entities;
static
{
Entity entity1 = new Entity() {{ id = 1; relatedThing = new Thing() {{ id = 42; }}; }};
Entity entity2 = new Entity() {{ id = 2; relatedThing = null; }};
entities = new HashMap<int, Entity>();
entities.put(entity1.id, entity1);
entities.put(entity2.id, entity2);
}
Requesting Entity References: If you request /Entities(1)/$ref, dictionary lookup will succeed and you will get a reference to the Entity with id of 1. But if you request /Entities(57)/$ref, the dictionary lookup will fail and you will get an error response (404).
Requesting Related Entities: If you request /Entities(1)/RelatedThing, dictionary lookup will succeed, the OData runtime will dereference the relatedThing property, and you will get a representation of the Thing object associated with the Entity. If you request /Entities(2)/RelatedThing, lookup succeeds, but dereferencing produces null. Note that the navigation property relatedThing exists (because the Entity exists), but there is no associated Thing (i.e., the cardinality of the association is 0..1). Since lookup succeeded, an error response (4xx) is not appropriate. And since dereferencing produced "nothing", the HTTP response code that indicates "no additional content to send in the response payload body" is completely appropriate.
I have a method that registers a new user using WebSecurity.CreateUserAndAccount(model.UserName, model.Password) The problem is that in the UserProfile model I have added a GUID Key. On my local machine this just populates an empty Guid when I call this method. On azure however, I get the following error:
System.Data.SqlClient.SqlException (0x80131904): Cannot insert the value NULL into column 'Key', table 'Scheduler.dbo.UserProfile'; column does not allow nulls. INSERT fails.
Now, I've tried to generate a new GUID in the constructor of the model, manually have the Set{} generate a new GUID and I get the same error.
When I try to use the CreateUserAndAccount overload like:
WebSecurity.CreateUserAndAccount(model.UserName, model.Password, new { Key = Guid.NewGuid() });
I get the following syntax error (run time):
Incorrect syntax near the keyword 'Key'.
I've spent a good part of the morning trying to figure this out and I just can't. By the way all of the above methods still result in an empty GUID 00000000-0000-0000-0000-000000000000 and the overload gives me syntax error on my local machine.
"Key" is a reserved word in SQL, it should be used in brackets like this [Key]
Since you don't have control on how WebSecurity generate the SQL query then your only option is to rename it to something like UserKey
The following code snapet throw an exception.
public Models.Web.User GetLogingUser(string username, string password)
{
using (Data.User_Repository repository = new Data.User_Repository())
{
IQueryable<Models.Web.User> query = repository.FindAll().Select(x =>new Models.Web.User()).Where(c => c.UserName.Equals(username.ToString())).AsQueryable();
return query.Where(x => x.Password.Equals(password.ToString())).First();
}
}
here the repositry class has the generic method insert, update, delete , find , findall etc.
during debugging I found that for the entered user name record are retrieved but when it assign to "query" variable i get the following error exception. kindly help me. thanks
"
The specified type member 'UserName' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported."
Its the .Equals() that is your issue. Use ==, since this is going to be executed on the database server, it will use the case comparison type which is configured for your database.
Getting an error client side with breeze: "Cannot call method 'map' of undefined" when trying to pull over some data. The difference between this action and one that works is that this action is calling a stored procedure and returning ObjectResult<T> instead of DbSet<T>.
Might this be why I get an error? Using Chrome Developer tools, I do see that the breeze controller is returning json data.
I have created a complex model type in the edmx for mapping the rows returned from the stored procedure.
The action in the breeze controller has a return type of IEnumerable<T>.
I experienced the same error when using an EF complex type. A workaround was to create a view in my database instead of using a complex type, set the stored procedure to return a type of the new view which had a primary key and then it worked. It would seem that breeze requires entities to have a primary key defined.
Hm... not quite sure what is happening, so just guessing here, but try adding an AsQueryable() to the result returned, and changing the result type to a IQueryable.
We don't have any stored proc tests for breeze yet, but this is impetus for me to add some :)
I had the very same issue, but thank God I figured out a solution. Instead of using a stored procedure, you should use a view, as Breeze recognizes views as DbSet<T>, just like tables. Say you have a SQL server table that contains two tables Customers and Orders.
Customers (**CustomerId**, FirstName, LastName)
Orders (OrderId, #CustomerId, OrderDate, OrderTotal)
Now, say you want a query that returns orders by CustomerId. Usually, you would do that in a stored procedure, but as I said, you need to use a view instead. So the query will look like this in the view.
Select o.OrderId, c.CustomerId, o.OrderDate, o.OrderTotal
from dbo.Orders o inner join dbo.Customers c on c.CustomerId = o.CustomerId
Notice there is no filtering (where ...). So:
i. Create a [general] view that includes the filtering key(s) and name it, say, OrdersByCustomers
ii. Add the OrdersByCustomers view to the entity model in your VS project
iii. Add the entity to the Breeze controller, as such:
public IQueryable<OrdersByCustomers> OrdersByCustomerId(int id)
{
return _contextProvider.Context.OrdersByCustomers
.Where(r => r.CustomerId == id);
}
Notice the .Where(r => r.CustomerId == id) filter. We could do it in the data service file, but because we want the user to see only his personal data, we need to filter from the server so it only returns his data.
iv. Now, that the entity is set in the controller, you may invoke it in the data service file, as such:
var getOrdersByCustomerId = function(orderObservable, id)
{
var query = breeze.EntityQuery.from('OrdersByCustomerId')
.WithParameters({ CustomerId: id });
return manager.executeQuery(query)
.then(function(data) {
if (orderObservable) orderObservable(data.results);
}
.fail(function(e) {
logError('Retrieve Data Failed');
}
}
v. You probably know what to do next from here.
Hope it helps.
I'm trying to get server-side validation of an Entity Framework String Property to work. Other server-side validation such as data type validation and required dateTime and numeric EF properties are working.
This in VS 2010, .Net 4.0, MVC2 + Cloud, ADO.Net Entity Framework.
The String Property I am having issues with is mapped to a SQL 2008, Varchar(50) non-nullable column.
When I try to post to my Create action with an empty string for this Property, I get the follwing error.
Exception Details: System.Data.ConstraintException: This property cannot be set to a null value.
When I post to the action with a blank space, I successfully get a required field validation message.
I have tried using Data Annotations and ClientSideValidation but there seems to be issues with ClientSideValidation working on partial views and jquery dialogs.
Here is the orginal autogenerated code from the entity framework.
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
[DataMemberAttribute()]
public global::System.String GradeTypeName
{
get
{
return GradeTypeName;
}
set
{
OnGradeTypeNameChanging(value);
ReportPropertyChanging("GradeTypeName");
_GradeTypeName = StructuralObject.SetValidValue(value, false);
ReportPropertyChanged("GradeTypeName");
OnGradeTypeNameChanged();
}
}
Depending on the signature of the Action method (CREATE or EDIT), the exception can occur before stepping into the method or within the method when UpdateModel() is called. The inner exception is at the line below from the model.designer.cs file.
_GradeTypeName = StructuralObject.SetValidValue(value, false);
I have been able to reproduce this on a simple mvc2 web application.
i was having the same problem for a while. I have found a piece of explanation here: http://mvcmusicstore.codeplex.com/workitem/6604 . To put it in a nutshell, the exception "System.Data.ConstraintException: This property cannot be set to a null value" is thrown by Entity's Property Validation. This validation is performed when your mvc application tries to bind the form field to the corresponding entity property( it's called PreBinding Validation, and it occurs when submitting the form). As the field is empty( therefore convert to null), the binder tries to bind a null value to the property, which violates the Non-Null constraint on your entity's property.
But if you post with a blank field ( that is different from empty, therefore null) Entity validation passes( as the property is not set to a null value anymore), and then your see the message from the "Required" annotation validation, that is performed after the prebinding (it's PostBinding Validation).
A workaround is to use the annotation [DisplayFormat(ConvertEmptyStringToNull = false)] that tells to the binder not to convert an empty string to null.
[Required]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string YourStringProperty { get; set;}
Hope, this helps!
This was very helpful. I'm using MVC3 and entity framework. I was passing my entities directly into the controller, but got the same error when the form was blank. With entity framework you can do data validation by editing the auto-generated code, but creating a separate partial class of the entity worked better for me.
[MetadataType(typeof(TestEntityValidation))]
public partial class TestEntity{
}
public class TestEntityValidation{
[Required]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public String name { get;set}
}
Sometimes in database first approach in EF, may you update your column from not null to can be null using SQL query and use 'Update Model From Database...' (in EDMX right click) then maybe property of that entity not updated properly and so if you have some null data in that column ,in mapping ,violation occurs and this error shown.
To fix this; You can check the Nullable in Properties of that property of entity that you updated it.