If you need a Property to have a primary PropertyImage that can only be an image that is applicable to that Property, the emphasis needs to be switched:
You cannot set the primary Image for a Property until the images are entered and related to the Property to begin with.
You can't add the images unless the Property exists to relate to.
So, you would need to have the PrimaryImage property nullable until later set.
While a PropertyImage relies on a Property, a Property does not rely on a PropertyImage, and so should not be a foreign key in it's record.
This means that the flag (boolean value) for PrimaryImage needs to be stored with the PropertyImage indicating which one of the images is the primary one.
Remove the PrimaryImageId from Property and place a property on the PropertyImage (IsPrimaryImage) to allow selection of the primary one.
You can handle the unique selection either via the UI or more properly with a Unique Constraint on the table.
public class Property
{
public int ID { get; set; }
public string Name { get; set; }
public ICollection<PropertyImage> Images { get; set; }
}
public class PropertyImage
{
[Key]
public Guid ID { get; set; }
public int PropertyID { get; set; }
public bool IsPrimaryImage { get;set; }
public virtual Property Property { get; set; }
}
It isn't good practice to try to structure the data and its relationships around the way you'd like to call a method in code.
You can still call the method the way you want and encapsulate any logic you may need inside.
Think along the lines of if there was a cascade delete applicable here to remove items that no longer have a parent item to relate to:
If you delete a Property, all related PropertyImages would be removed too - correctly so because they relied on that record existing.
If you delete the primary PropertyImage, then the Property would have to be deleted because the record it relates to no longer exists...
So to have your method call the way you would like, do something similar to this:
private void UpdatePrimaryImage(PropertyImage oldImage, PropertyImage newImage)
{
// Pass in the original primary PropertyImage and the new one obtained from the UI.
// Check that we do not have the same image, otherwise no change needs to be made:
if(oldImage.IsPrimary != newImage.IsPrimary)
{
oldImage.IsPrimary = false;
newImage.IsPrimary = true;
Update(oldImage);
Update(newImage);
SaveChanges;
}
}
And to retrieve the current primary image:
Property.PropertyImages.Where(p => p.IsPrimaryImage).Url