Reputation: 12440
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. I am using EF CPT5
The Model:
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 long ThumbnailId { 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<br/>{ get { return _dateCreated; } set { _dateCreated = value; } }
public long AlbymId { get; set; }
public virtual Album Album { get; set; }
}
The Mapping Code:
public class AlbumMap : EntityTypeConfiguration<Album> {
public AlbumMap() {
HasRequired(x => x.Thumbnail).WithMany().HasForeignKey(a => a.ThumbnailId).WillCascadeOnDelete(false);
Property(x => x.Location).IsVariableLength().HasMaxLength(80);
Property(x => x.Name).IsVariableLength().HasMaxLength(80).IsRequired();
}
}
public class PhotoMap : EntityTypeConfiguration<Photo> {
public PhotoMap() {
HasRequired(p => p.Album).WithMany(a => a.Photos).HasForeignKey(p => p.AlbymId);
Property(x => x.FileName).IsVariableLength().HasMaxLength(255).IsRequired();
Property(x => x.Caption).IsVariableLength().HasMaxLength(255);
Property(x => x.DateCreated);
ToTable("SiteAlbumPhotos");
}
}
Context
public class Database : ObjectContext {
public Database(EntityConnection connection) : base(connection) {
ContextOptions.LazyLoadingEnabled = true;
ContextOptions.ProxyCreationEnabled = true;
}
private IObjectSet<User> _users;
private IObjectSet<Site> _sites;
private IObjectSet<SiteDonation> _donations;
private IObjectSet<SiteAnnouncement> _siteAnnouncements;
private IObjectSet<SiteData> _siteData;
private IObjectSet<SiteLink> _siteLinks;
private IObjectSet<SitePost> _sitePosts;
private IObjectSet<Theme> _theme;
private IObjectSet<Album> _siteAlbums;
private IObjectSet<Photo> _siteAlbumPhotos;
private IObjectSet<CommunityPost> _communityPosts;
private IObjectSet<CommunityComment> _communityComments;
public IObjectSet<User> Users {
get{ return _users ?? (_users = ObjectSet<User>()); }
}
public IObjectSet<Album> SiteAlbums {
get { return _siteAlbums ?? (_siteAlbums = ObjectSet<Album>()); }
}
public IObjectSet<Photo> SiteAlbumsPhotos {
get { return _siteAlbumPhotos ?? (_siteAlbumPhotos = ObjectSet<Photo>()); }
}
public IObjectSet<Site> Sites {
get{ return _sites ?? (_sites = ObjectSet<Site>()); }
}
public IObjectSet<SiteDonation> SiteDonations {
get { return _donations ?? (_donations = ObjectSet<SiteDonation>()); }
}
public IObjectSet<SiteAnnouncement> SiteAnnouncements {
get { return _siteAnnouncements ?? (_siteAnnouncements = ObjectSet<SiteAnnouncement>()); }
}
public IObjectSet<SiteData> SiteData {
get { return _siteData ?? (_siteData = ObjectSet<SiteData>()); }
}
public IObjectSet<SiteLink> SiteLinks {
get { return _siteLinks ?? (_siteLinks = ObjectSet<SiteLink>()); }
}
public IObjectSet<SitePost> SitePosts {
get { return _sitePosts ?? (_sitePosts = ObjectSet<SitePost>()); }
}
public IObjectSet<Theme> Themes {
get { return _theme ?? (_theme = ObjectSet<Theme>()); }
}
public IObjectSet<CommunityPost> CommunityPosts {
get { return _communityPosts ?? (_communityPosts = ObjectSet<CommunityPost>()); }
}
public IObjectSet<CommunityComment> CommunityComments {
get { return _communityComments ?? (_communityComments = ObjectSet<CommunityComment>()); }
}
public virtual IObjectSet<T> ObjectSet<T>() where T : class, IEntity {
return CreateObjectSet<T>();
}
public virtual void Commit() {
SaveChanges();
}
}
DatabaseFactory
public class DatabaseFactory : Disposable, IDatabaseFactory
{
private static readonly ModelBuilder builder = CreateBuilder();
private readonly DbProviderFactory _providerFactory;
private readonly string _connectionString;
private Database _database;
//
public DatabaseFactory(DbProviderFactory providerFactory, string connectionString)
{
Check.Argument.IsNotNull(providerFactory, "providerFactory");
Check.Argument.IsNotNullOrEmpty(connectionString, "connectionString");
_providerFactory = providerFactory;
_connectionString = connectionString;
}
//
public Database Get()
{
if(_database == null)
{
var connection = _providerFactory.CreateConnection();
connection.ConnectionString = _connectionString;
//_database = builder.CreateModel(connection); LEG 1 CPT 3
//var ctx = dbModel.CreateObjectContext<ObjectContext>(_connectionString); LEG 1 CPT 3
//var modelBuilder = builder.CreateModel(); LEG 2 CPT 4
//_database = modelBuilder.CreateObjectContext<Database>(connection); LEG 2 CPT 4
//_database = modelBuilder.CreateObjectContext<Database>(connection); LEG 2 CPT 4
var modelBuilder = builder.Build(connection);
var dbModel = new DbModel(modelBuilder);
_database = dbModel.CreateObjectContext<Database>(connection);
}
return _database;
}
//
protected override void DisposeCore()
{
if (_database != null)
{
_database.Dispose();
}
}
//
private static ModelBuilder CreateBuilder()
{
//ContextBuilder<Database> contextBuilder = new ContextBuilder<Database>();
var contextBuilder = new ModelBuilder();
//IEnumerable<Type> configurationTypes = typeof(DatabaseFactory)
// .Assembly
// .GetTypes()
// .Where(type => type.IsPublic && type.IsClass && !type.IsAbstract && !type.IsGenericType && typeof(StructuralTypeConfiguration).IsAssignableFrom(type) && (type.GetConstructor(Type.EmptyTypes) != null));
//foreach (StructuralTypeConfiguration configuration in configurationTypes.Select(type => (StructuralTypeConfiguration)Activator.CreateInstance(type)))
//{
// contextBuilder.Configurations.Add(configuration);
//}
contextBuilder.Configurations.Add(new CommunityCommentMap());
contextBuilder.Configurations.Add(new CommunityPostMap());
contextBuilder.Configurations.Add(new SiteAlbumMap());
contextBuilder.Configurations.Add(new SiteAlbumPhotoMap());
contextBuilder.Configurations.Add(new SiteAnnouncementMap());
contextBuilder.Configurations.Add(new SiteDataMap());
contextBuilder.Configurations.Add(new SiteDonationMap());
contextBuilder.Configurations.Add(new SiteLinkMap());
contextBuilder.Configurations.Add(new SiteMap());
contextBuilder.Configurations.Add(new SitePostMap());
contextBuilder.Configurations.Add(new ThemeMap());
contextBuilder.Configurations.Add(new UserMap());
return contextBuilder;
}
}
Am I Modeling and Mapping this correctly? I need to be able to create a new Album without specifying a Thumbnail. As of now, it all works till I try to add a Thumbnail, then I get this error:
System.Data.UpdateException: Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values.
at System.Data.Mapping.Update.Internal.UpdateTranslator.DependencyOrderingError(IEnumerable`1 remainder) at System.Data.Mapping.Update.Internal.UpdateTranslator.ProduceCommands() at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter) at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options) at PostHope.Infrastructure.DataAccess.Database.Commit() in Database.cs: line 74 at PostHope.Infrastructure.DataAccess.IntegrationTests.BuildDatabase.Add_test_data_to_database() in BuildDatabase.cs: line 252
Any help would be great!
Upvotes: 2
Views: 2314
Reputation: 33206
We tackled this question by EF CTP4 here. Now here is the update for EF CTP5 which has been released earlier today.
public class Photo
{
public long PhotoId { get; set; }
[MaxLength(255)]
public string Caption { get; set; }
[MaxLength(255)][Required]
public string FileName { get; set; }
public DateTime DateCreated { get; set; }
public long AlbumId { get; set; }
public virtual Album Album { get; set; }
}
[Table("SiteAlbumPhotos")]
public class Album
{
public long AlbumId { get; set; }
[MaxLength(80)][Required]
public string Name { get; set; }
[MaxLength(80)]
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 : EntityTypeConfiguration<Photo> {
public PhotoMap() {
HasRequired(p => p.Album).WithMany(a => a.Photos)
.HasForeignKey(p => p.AlbumId);
}
}
public class AlbumMap : EntityTypeConfiguration<Album> {
public AlbumMap() {
HasRequired(a => a.Thumbnail).WithMany()
.HasForeignKey(a => a.ThumbnailId)
.WillCascadeOnDelete(false);
}
}
public class MyContext : DbContext {
public DbSet<Photo> Photos { get; set; }
public DbSet<Album> Albums { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder.Configurations.Add<Photo>(new PhotoMap());
modelBuilder.Configurations.Add<Album>(new AlbumMap());
}
}
Which results to this DB schema:
Upvotes: 2