1
votes

I have an AngularJS SPA using Breeze, Web API, and Entity Framework (code first). How do I create a new Breeze entity with a foreign-key reference to an existing entity?

I have tried building off these examples, but some of them assume the use of Knockout rather than AngularJS.

http://www.breezejs.com/documentation/add-new-entity

http://www.breezejs.com/documentation/creating-entities

I have tried to add a new ScheduleTask entity many different ways, but they all give the same error:

Server side errors encountered - see the entityErrors collection on this object for more detail

The User field is required.

Here are the relevant pieces of code (TypeScript on the client and C# on the server). I know I am doing some naughty things like blindly saving changes, but I wanted to make this as simple as possible.

Breeze configuration:

breeze.config.initializeAdapterInstance("modelLibrary", "backingStore", true);

Controller method:

[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
    return this.repository.SaveChanges(saveBundle);
}

Parent model:

public class User
{
    [Key]
    public int UserId { get; set; }

    public ICollection<ScheduleTask> ScheduleTasks { get; set; } 
}

Child model:

public class ScheduleTask
{
    [Key]
    public int ScheduleTaskId { get; set; }

    [Required]
    public int UserId { get; set; }
    [ForeignKey("UserId"), Required]
    public User User { get; set; }
}

Attempt 1:

var entity: any = this.manager.createEntity('ScheduleTask');
    entity.UserId = 1;
    this.manager.saveChanges([entity])
        .then(() => {
            alert("Success!");
        })
        .fail((error) => {
            alert(error.message + '\n' + error.entityErrors[0].errorMessage);
        });

Attempt 2:

var entity: any = this.manager.createEntity('ScheduleTask', { UserId: 1 });
this.manager.saveChanges([entity])
    .then(() => {
        alert("Success!");
    })
    .fail((error) => {
        alert(error.message + '\n' + error.entityErrors[0].errorMessage);
    });

Attempt 3:

var query = breeze.EntityQuery.from("Users").top(1);
this.manager.executeQuery(query)
    .then((users) => {
        var user = users.results[0];
        var entity: any = this.manager.createEntity('ScheduleTask');
        user.ScheduleTasks.push(entity);
        this.manager.saveChanges()
            .then(() => {
                alert("Success!");
            })
            .fail((error) => {
                alert(error.message + '\n' + error.entityErrors[0].errorMessage);
            });
    })
    .fail((error) => {
        alert(error.message);
    });

Attempt 4:

var query = breeze.EntityQuery.from("Users").top(1);
this.manager.executeQuery(query)
    .then((users) => {
        var user = users.results[0];
        var entity: any = this.manager.createEntity('ScheduleTask', { User: user });
        this.manager.saveChanges()
            .then(() => {
                alert("Success!");
            })
            .fail((error) => {
                alert(error.message + '\n' + error.entityErrors[0].errorMessage);
            });
    })
    .fail((error) => {
        alert(error.message);
    });
1

1 Answers

1
votes

Oh, great. I spent hours trying to get this to work, then the answer came to me as soon as I posted the question. I just had to get rid of the Required attribute on ScheduleTask.User, and it works fine:

[Required]
public int UserId { get; set; }
[ForeignKey("UserId"), Required]
public User User { get; set; }

Since UserId still has the Required attribute, EF makes it not nullable.

I ended up using attempt #2 in the question, but the problem was on the server side.