Propel unsets primary key when saved twice - symfony1

Consider we have the following model class Model generated by Propel. Furthermore we use the sfPropelORMPlugin to generate forms and filters.
We create a Model instance using ModelForm as follows.
$form = new ModelForm();
$form->getObject()->save();
// first var_dump
var_dump($form->getObject()->getId());
$form->bind(array(), array());
$form->save();
// second var_dump
var_dump($form->getObject()->getId()); exit();
Running a simple unit test will for example give the following result.
int(100) // say the auto_increment value of the PK starts at 100
NULL
Why does the second var_dump return NULL? Is this desired behaviour? Or is this a bug in either Propel or sfPropelORMPlugin?
The issue exists with at least Propel version 1.7.0 .

Related

ASP.NET MVC Model First Many To Many

I have some problems working with model first many to many relationship. Since I created many-many relationship between Town and Author via interface builder it created table TownAuthor with keys Towns_TownID and Authors_AuthorID but I want that just to be called TownID and AuthorID, how do I change that?
In Code first I would use that modelBuilder configuration in Context but I have no idea how to do this via model first...
You have to change the names of these columns in the Entity Designer DDL script (which is generated from the EDMX file and has ModelName.edmx.sql name) before executing it.
-- Creating table 'TownAuthor'
CREATE TABLE [dbo].[TownAuthor] (
[TownID] int NOT NULL,
[AuthorID] int NOT NULL
);
GO

grails validation when fetching rows

Is it possible to fetch a default value in grails if a column is null? If I were to represent following query via grails domain object then how could I achieve it:
SELECT IFNULL(empsalary,0.00) from Employee;
Domain object:
class Employee{
Integer id,
Float empsalary
static constraints = {
id unique: true, blank:false
empsalary nullable:true
}
}
making empsalary nullable false isn't an option due to existing data
validator on empsalary seems to work when inserting rows but not while data fetch
we can consider writing say getEmpSalary() method on domain and perform check there but there are several other fields we need to do this so trying to avoid massive code changes
If you want a default value to come out of the database without having to code anything into your classes, I suggest you update every row where it is null and set it to 0 in the database. If data is getting inserted from another application and that application is allowing a null value, put a 'DEFAULT 0' on your database column.
Grails also offers an "afterLoad" event which is run when a domain object gets loaded from the database. See the documentation here: http://grails.org/doc/2.3.7/guide/GORM.html.
I think you can do this with HQL:
def salary = Employee.executeQuery('SELECT COALESCE(empsalary, 0.0) FROM Employee')[0]
See this SO Question.
Please try setting Float empsalary = 0.0 in your domain object.

Websecurity.CreateUserAndAccount on Azure doesn't work

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

Error in breeze using EF 5 and calling stored procedure

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.

How to bypass the System.Data.Entity.Internal.InternalPropertyEntry.ValidateNotDetachedAndInModel(String method) validation of Entity framework?

I'm using a customized method for tracking individual modified properties of an n-tier disconnected entity class. I extracted it from
Programming Entity Framework: DbContext by Julia Lerman and Rowan
Miller (O’Reilly). Copyright 2012 Julia Lerman and Rowan Miller,
978-1-449-31296-1.
The code is:
public void ApplyChanges<TEntity>(TEntity root) where TEntity : class, IObjectWithState {
// bind the entity back into the context
dbContext.Set<TEntity>().Add(root);
// throw exception if entity does not implement IObjectWithState
CheckForEntitiesWithoutStateInterface(dbContext);
foreach (var entry in dbContext.ChangeTracker.Entries<IObjectWithState>()) {
IObjectWithState stateInfo = entry.Entity;
if (stateInfo.State == RecordState.Modified) {
// revert the Modified state of the entity
entry.State = EntityState.Unchanged;
foreach (var property in stateInfo.ModifiedProperties) {
// mark only the desired fields as modified
entry.Property(property).IsModified = true;
}
} else {
entry.State = ConvertState(stateInfo.State);
}
}
dbContext.SaveChanges();
}
The purpose of this method is to let the EF know only a predefined set of entity fields are ready for update in the next call of SaveChanges(). This is needed in order to workaround the entity works in ASP.NET MVC 3 as follows:
on initial page load: the Get action of the controller is loading the
entity object and passing it as a parameter to the view.
The View generate controls for editing 2 of the fields of the entity,
and holds the ID of the record in a hidden field.
When hitting [save] and posting the entity back to the controller all
of the fields excepting the 3 preserved in the view comes with a null
value. This is the default behavior of the MVC binding manager.
If i save the changes back to the database the update query will of course overwrite the non mapped fields with a sentence as follows:
UPDATE non_mapped_field_1 = NULL, ..., mapped_field_1 = 'mapped_value_1', mapped_field_2 = 'mapped_value_2', ... non_mapped_field_n = NULL WHERE ID = mapped_field_3
This is the reason i'm trying to track the fields individually and update only those fields i'm interested in. before calling the custom method with ApplyChanges() i'm adding the list of fields i want to be included in the update to the IObjectWithState.ModifiedProperties list, in order to get a SQL statement as follows:
UPDATE mapped_field_1 = 'mapped_value_1', mapped_field_2 = 'mapped_value_2' WHERE id = mapped_value_3
The problem is, when marking one of the fields as modified in ApplyChanges, i.e.:
entry.Property(property).IsModified = true;
the system is throwing the following exception:
{System.InvalidOperationException: Member 'IsModified' cannot be called for property 'NotifyCEDeadline' on entity of type 'User' because the property is not part of the Entity Data Model.
at System.Data.Entity.Internal.InternalPropertyEntry.ValidateNotDetachedAndInModel(String method)
at System.Data.Entity.Internal.InternalPropertyEntry.set_IsModified(Boolean value)
at System.Data.Entity.Infrastructure.DbPropertyEntry.set_IsModified(Boolean value)
...
So the question is. There's a way to bypass this EF validation or let the context know of the existance of this system property (IsModified) that i'm trying to change?
Summary of the architeture:
EF Code first (annotation + Fluent API)
Oracle .NET EF Data provider (ODAC)
Context is injected to a cutom business context with nInject.MVC => this is the reason i customized the ApplyChanges() method from
using (var context = new BreakAwayContext()){
context.Set().Add(root);
to a simple call to the already initialized dbcontext
dbContext.Set().Add(root);
Oracle Database is created manually i.e. without the help of EF, so no EF metadata tables are used.
Thanks,
Ivan.
Very good description, however I can't find any information on why you need a transient property called "IsModified" in the object and/or why you need to tell EF about it being modified (EF won't be able to persist it anyway).
The value of the IsModified property should be set by the model binder if the property was incldued in the view anyway.
You could just add code in your ApplyChanges method to skip a property named "IsModified", or even better, filter only known properties using entry.CurrentValues.PropertyNames, e.g.:
foreach (var property in stateInfo.ModifiedProperties) {
// mark only the desired fields as modified
if (entry.CurrentValues.PropertyNames.Contains(property)) {
entry.Property(property).IsModified = true;
}
}
Update: Ivan, very sorry I did not understand the problem better when you posted it several months ago and that I did not follow up after your added these clarifying comments. I think I understand better now. That said, I think the code snippet that I offered can be part of the solution. From looking at the exception you are getting again, I understand now that the problem that EF is detecting is that NotifyCEDDealine is not a persistent property (i.e. it is not mapped in the Code First model to a column in the database). IsModified can only be used against mapped properties, therefore you have two options: you change the code of the implementation of IObjectWithState in your entities so that non-mapped properties are not recorded in ModifiedProperties, or you use my code snippet to prevent calling IsModified with those.
By the way, an alternative to doing all this is to use the Controller.TryUpdateModel API to set only the modified properties in your entities.
Hope this helps (although I understand it is very late).

Resources