views:

37

answers:

2

I have 2 tables Jobs and Schedule

Jobs

JobId - int,PK, Identity
ScheduleId - int, FK
Title - varchar
Description - varchar

Schedules

ScheduleId - int,PK, Identity
Name - varchar

There is a relationship one to many with cascade on delete.

When I create Entity model, the generated Jobs model removes the ScheduleId field.

The Problem is that I can't Insert new Job with specified ScheduleId!

 Job job = new Job();
 job.title= "blabla";
 job.description="xyz";
 job.scheduleId=1// can't have this!

 if (job.EntityState == EntityState.Detached)
 {
      myContext.AddToJobs(job);
 }
 myContext.SaveChanges();

Note: I have a row in Schedules table with scheduleId=1.

A: 

Doesn't the entity framework created a navigation property called Schedule?

You can use:

 Schedule schedule = // Get here the schedule with Id == 1;
 Job job = new Job();
 job.title= "blabla";
 job.description="xyz";
 job.schedule = schedule; //<-- Use the navigation property

 if (job.EntityState == EntityState.Detached)
 {
      myContext.AddToJobs(job);
 }
 myContext.SaveChanges();

The Id assignment is handled internally by the framework.


Here is a sample of a Job and a Schedule class created by Entity Framework with the POCO T4. Including the navigation property and the ScheduleId. Notice that the ScheduleId and Schedule Proprerties in the Job class are totaly binded one to the other.

public partial class Job
{
    #region Primitive Properties

    public virtual int Id
    {
        get;
        set;
    }

    public virtual int ScheduleId
    {
        get { return _scheduleId; }
        set
        {
            if (_scheduleId != value)
            {
                if (Schedule != null && Schedule.Id != value)
                {
                    Schedule = null;
                }
                _scheduleId = value;
            }
        }
    }
    private int _scheduleId;

    public virtual string Title
    {
        get;
        set;
    }

    public virtual string Description
    {
        get;
        set;
    }

    #endregion
    #region Navigation Properties

    public virtual Schedule Schedule
    {
        get { return _schedule; }
        set
        {
            if (!ReferenceEquals(_schedule, value))
            {
                var previousValue = _schedule;
                _schedule = value;
                FixupSchedule(previousValue);
            }
        }
    }
    private Schedule _schedule;

    #endregion
    #region Association Fixup

    private void FixupSchedule(Schedule previousValue)
    {
        if (previousValue != null && previousValue.Job.Contains(this))
        {
            previousValue.Job.Remove(this);
        }

        if (Schedule != null)
        {
            if (!Schedule.Job.Contains(this))
            {
                Schedule.Job.Add(this);
            }
            if (ScheduleId != Schedule.Id)
            {
                ScheduleId = Schedule.Id;
            }
        }
    }

    #endregion
}

public partial class Schedule
{
    #region Primitive Properties

    public virtual int Id
    {
        get;
        set;
    }

    public virtual string Description
    {
        get;
        set;
    }

    #endregion
    #region Navigation Properties

    public virtual ICollection<Job> Job
    {
        get
        {
            if (_job == null)
            {
                var newCollection = new FixupCollection<Job>();
                newCollection.CollectionChanged += FixupJob;
                _job = newCollection;
            }
            return _job;
        }
        set
        {
            if (!ReferenceEquals(_job, value))
            {
                var previousValue = _job as FixupCollection<Job>;
                if (previousValue != null)
                {
                    previousValue.CollectionChanged -= FixupJob;
                }
                _job = value;
                var newValue = value as FixupCollection<Job>;
                if (newValue != null)
                {
                    newValue.CollectionChanged += FixupJob;
                }
            }
        }
    }
    private ICollection<Job> _job;

    #endregion
    #region Association Fixup

    private void FixupJob(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null)
        {
            foreach (Job item in e.NewItems)
            {
                item.Schedule = this;
            }
        }

        if (e.OldItems != null)
        {
            foreach (Job item in e.OldItems)
            {
                if (ReferenceEquals(item.Schedule, this))
                {
                    item.Schedule = null;
                }
            }
        }
    }

    #endregion
}
Sir Gallahad
So to create Job and pass int value I MUST use Schedule object?! why there is no direct way to achieve that?
shlomjmi
There is. But it would require to customize the object in the entity framework or adding it as a partial implementaion of the class generated by the EF.I can try to post a sample here for you in a couple of hours...
Sir Gallahad
I'll appreciate it.
shlomjmi
A: 

You can assign Schedule without actually loading Schedule object. Something like this:

db = new OneToManyEntities(); 
var address = new Address { Address1 = "Oakumber st", City = "Dallas", State = "Tx", Zip = "76111" }; 
address.CustomerReference.EntityKey = new EntityKey("OneToManyEntities.Customer","CustomerId",2); 
db.AddToAddresses(address);

I don't like this approach, case you have to hardcode entity types in string :/ If anyone know how to do this without such hardcoding - please comment.

lak-b