I have this simple data model of some reservations and theirs cancellations:
[Table("ReservationCreation")]
public class ReservationCreation
{
[Key()]
public int ReservationCreationId { get; set; }
[InverseProperty("ReservationCreation")]
public virtual ReservationCancellation ReservationCancellation { get; set; }
}
[Table("ReservationCancellation")]
public class ReservationCancellation
{
[Key()]
[ForeignKey("ReservationCreation")]
public int ReservationCancellationId { get; set; }
[Required]
[ForeignKey("ReservationCancellationId")]
[InverseProperty("ReservationCancellation")]
public virtual ReservationCreation ReservationCreation { get; set; }
}
public class DbContext : System.Data.Entity.DbContext
{
public DbContext() : base(@"DefaultConnection") { }
public DbSet<ReservationCancellation> ReservationCancellation { get; set; }
public DbSet<ReservationCreation> ReservationCreation { get; set; }
}
internal sealed class Configuration : DbMigrationsConfiguration<DbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
}
Here is the code of the test. First the reservation is created and then it is cancelled. When the cancellation record is being saved into database then an exception is thrown "The ReservationCreation field is required". How can I create cancellation record only from the reservation's ID and at the same time have the navigation properties defined?
class Program
{
static void Main(string[] args)
{
int reservationId;
// create reservation
using (var db = new DbContext())
{
var reservation =
db.ReservationCreation.Add(
new ReservationCreation());
db.SaveChanges();
reservationId = reservation.ReservationCreationId;
}
// cancel reservation by its Id
using (var db = new DbContext())
{
var cancellation =
db.ReservationCancellation.Add(
new ReservationCancellation
{
ReservationCancellationId = reservationId
});
try
{
// an exception is thrown
db.SaveChanges();
}
catch(DbEntityValidationException ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
foreach (var err in ex.EntityValidationErrors.SelectMany(x_ => x_.ValidationErrors))
System.Diagnostics.Debug.WriteLine($"!!!ERROR!!! {err.PropertyName}: {err.ErrorMessage}");
}
}
}
}
I did not find any way how to modify the data model annotations. If I remove [Required] from ReservationCreation property then I am not able to create the migration {or connect to the database with that data model).
Your mixing things up in your ReservationCancellation
model.
In your ReservationCreation
property you are referring to the primary key entity instead of the ReservationCreation property.
Try this.
[Table("ReservationCancellation")]
public class ReservationCancellation
{
[Key()]
public int ReservationCancellationId { get; set; }
[ForeignKey("ReservationCreation")]
public int ReservationCreationId { get; set; }
[Required]
public virtual ReservationCreation ReservationCreation { get; set; }
}
Since you want only one cancellation per creation, you can do this using a simpler model.
[Table("ReservationCreation")]
public class ReservationCreation
{
[Key()]
public int ReservationCreationId { get; set; }
public virtual ReservationCancellation ReservationCancellation { get; set; }
}
[Table("ReservationCancellation")]
public class ReservationCancellation
{
[Key()]
public int ReservationCancellationId { get; set; }
public virtual ReservationCreation ReservationCreation { get; set; }
}