I am trying to model out a album that has a collection of photos. Each Album will have a collection of Photos and a Photo that is a thumb. This is what I have but EF does not seem to like it:
public class Album : IEntity {
private DateTime _dateCreated;
public Album() {
_dateCreated = SystemTime.Now();
Photos = new List<Photo>();
}
public long Id { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public DateTime DateCreated
{
get { return _dateCreated; }
set { _dateCreated = value; }
}
public virtual Site Site { get; set; }
public virtual Photo Thumbnail { get; set; }
public virtual ICollection<Photo> Photos { get; set; }
}
public class Photo : IEntity {
public Photo() {
_dateCreated = SystemTime.Now();
}
private DateTime _dateCreated;
public long Id { get; set; }
public string Caption { get; set; }
public string FileName { get; set; }
public DateTime DateCreated
{
get { return _dateCreated; }
set { _dateCreated = value; }
}
public virtual Album Album { get; set; }
}
public class AlbumMap : EntityConfiguration<Album>
{
public AlbumMap()
{
HasKey(x => x.Id);
Property(x => x.Id).IsIdentity();
Property(x => x.Location).IsVariableLength().HasMaxLength(80);
Property(x => x.Name).IsVariableLength().HasMaxLength(80).IsRequired();
Property(x => x.DateCreated);
MapSingleType(a => new
{
a.Id,
SiteId = a.Site.Id,
ThumbnailId = a.Thumbnail.Id,
a.Location,
a.Name,
a.DateCreated
}).ToTable("Albums");
}
}
public class PhotoMap : EntityConfiguration<Photo>
{
public PhotoMap()
{
HasKey(x => x.Id);
Property(x => x.Id).IsIdentity();
Property(x => x.FileName).IsVariableLength().HasMaxLength(255).IsRequired();
Property(x => x.Caption).IsVariableLength().HasMaxLength(255);
Property(x => x.DateCreated);
MapSingleType(a => new
{
a.Id,
SiteAlbumId = a.Album.Id,
a.FileName,
a.Caption,
a.DateCreated
}).ToTable("AlbumPhotos");
}
}
Am I missing something or does this look right? I am expecting EF to generate a 1 to many in my database but it keeps creating a reference table between Album and Photos (Album_Photos) but this should not be a many-to-many. Any help would be great.
The Domain Model is an object model of the domain that incorporates both behavior and data. In the example of the e-commerce app, we need to deal with the domain logic of customers who want to buy products and return them if they want.
The domain model is a representation of meaningful real-world concepts pertinent to the domain that need to be modeled in software. The concepts include the data involved in the business and rules the business uses in relation to that data. A domain model leverages natural language of the domain.
By convention, EF code first does not create a link table in typical one to many scenario, the reason that you are getting it is because your associations between Album and Photo objects has been taken by EF as being a kind of many to many association:
Each album has a collection of Photos and also each Photo has a collection of Albums that this photo is a thumbnail for (although the related navigation property is not explicitly specified on Photo class and only Album has a Thumbnail property).
As of EF CTP4, the only way to fix this is by leveraging Fluent API, but before that, I modify your model a little bit and add two explicit FKs to your model to give you ultimate flexibility to work with your objects. They are AlbumId
on Photo
and ThumbnailId
on Album
:
public class Photo {
public long Id { get; set; }
public string Caption { get; set; }
public string FileName { get; set; }
public DateTime DateCreated { get; set; }
public long AlbumId { get; set; }
public virtual Album Album { get; set; }
}
public class Album {
public long Id { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public DateTime DateCreated { get; set; }
public long ThumbnailId { get; set; }
public virtual Photo Thumbnail { get; set; }
public virtual ICollection<Photo> Photos { get; set; }
}
public class PhotoMap : EntityConfiguration<Photo> {
public PhotoMap()
{
this.HasRequired(p => p.Album)
.WithMany(a => a.Photos)
.HasConstraint((p, a) => p.AlbumId == a.Id);
Property(x => x.FileName).IsVariableLength().HasMaxLength(255)
.IsRequired();
Property(x => x.Caption).IsVariableLength().HasMaxLength(255);
MapSingleType(p => new {
p.Id,
SiteAlbumId = p.AlbumId,
p.FileName,
p.Caption,
p.DateCreated
})
.ToTable("Photo");
}
}
public class AlbumMap : EntityConfiguration<Album> {
public AlbumMap()
{
this.HasRequired(a => a.Thumbnail)
.WithMany()
.WillCascadeOnDelete(false)
.HasConstraint((a, p) => p.Id == a.ThumbnailId);
Property(x => x.Location).IsVariableLength().HasMaxLength(80);
Property(x => x.Name).IsVariableLength().HasMaxLength(80).IsRequired();
MapSingleType(a => new {
a.Id,
a.ThumbnailId,
a.Location,
a.Name,
a.DateCreated
})
.ToTable("Album");
}
}
This results to the following desired schema:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With