У меня проблемы с отображением объектов базы данных в модели WPF и обратно. Мое приложение работает с моделью WPF, которая реализует интерфейс INotifyPropertyChanged. Каждый раз, когда мне нужно сохранить его в базе данных, мне нужно сопоставить мою модель WPF с моделью базы данных. Я создал сложный картограф для этого, но в итоге у него была циклическая зависимость. Как я могу эффективно сопоставить мою модель WPF с моделью базы данных? Моя модель базы данных:
public class DbUser
{
[Key]
public Guid UserId { get; set; }
public List<DbSeries> UserSeries { get; set; }
}
public class DbSeries
{
[Key]
public Guid SeriesId { get; set; }
public List<DbDropPhoto> DropPhotosSeries { get; set; }
public virtual DbReferencePhoto ReferencePhotoForSeries { get; set; }
public Guid CurrentUserId { get; set; }
public DbUser CurrentUser { get; set; }
}
public class DbReferencePhoto
{
[Key]
public Guid ReferencePhotoId { get; set; }
public virtual DbSimpleLine SimpleLine { get; set; }
public virtual DbSeries Series { get; set; }
}
public class DbDropPhoto
{
[Key]
public Guid DropPhotoId { get; set; }
public virtual DbSimpleLine SimpleHorizontalLine { get; set; }
public virtual DbSimpleLine SimpleVerticalLine { get; set; }
public virtual DbDrop Drop { get; set; }
public Guid CurrentSeriesId { get; set; }
public DbSeries CurrentSeries { get; set; }
}
public class DbDrop
{
[Key]
public Guid DropId { get; set; }
public virtual DbDropPhoto DropPhoto { get; set; }
}
public class DbSimpleLine
{
[Key]
public Guid SimpleLineId { get; set; }
public virtual DbReferencePhoto ReferencePhoto { get; set; }
public virtual DbDropPhoto DropPhotoHorizontalLine { get; set; }
public virtual DbDropPhoto DropPhotoVerticalLine { get; set; }
}
конфигурация беглого API выглядит следующим образом:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<DbUser>()
.HasMany(s => s.UserSeries)
.WithRequired(g => g.CurrentUser)
.HasForeignKey(s => s.CurrentUserId);
modelBuilder.Entity<DbSeries>()
.HasMany(s => s.DropPhotosSeries)
.WithRequired(g => g.CurrentSeries)
.HasForeignKey(s => s.CurrentSeriesId)
.WillCascadeOnDelete();
modelBuilder.Entity<DbSeries>()
.HasRequired(s => s.ReferencePhotoForSeries)
.WithRequiredPrincipal(ad => ad.Series);
modelBuilder.Entity<DbDropPhoto>()
.HasRequired(s => s.Drop)
.WithRequiredPrincipal(ad => ad.DropPhoto);
modelBuilder.Entity<DbDropPhoto>()
.HasRequired(s => s.SimpleHorizontalLine)
.WithRequiredPrincipal(ad => ad.DropPhotoHorizontalLine);
modelBuilder.Entity<DbDropPhoto>()
.HasRequired(s => s.SimpleVerticalLine)
.WithRequiredPrincipal(ad => ad.DropPhotoVerticalLine);
modelBuilder.Entity<DbReferencePhoto>()
.HasRequired(s => s.SimpleLine)
.WithRequiredPrincipal(ad => ad.ReferencePhoto);
}
моя модель WPF:
public class User : INotifyPropertyChanged
{
public User()
{
_userSeries = new ObservableCollection<Series>();
_userSeries.CollectionChanged += _userSeries_CollectionChanged;
}
private void _userSeries_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsAnySelectedSeriesCanDrawPlot)));
}
public Guid UserId { get; set; }
private ObservableCollection<Series> _userSeries;
public ObservableCollection<Series> UserSeries
{
get
{
return _userSeries;
}
set
{
_userSeries = value;
OnPropertyChanged(new PropertyChangedEventArgs("UserSeries"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChanged?.Invoke(this, e);
}
}
public class Series : INotifyPropertyChanged
{
private Guid _currentUserId;
public Guid CurrentUserId
{
get
{
return _currentUserId;
}
set
{
_currentUserId = value;
OnPropertyChanged(new PropertyChangedEventArgs("CurrentUserId"));
}
}
private User _currentUser;
public User CurrentUser
{
get
{
return _currentUser;
}
set
{
_currentUser = value;
OnPropertyChanged(new PropertyChangedEventArgs("CurrentUser"));
}
}
public Series()
{
_dropPhotosSeries = new ObservableCollection<DropPhoto>();
_dropPhotosSeries.CollectionChanged += _dropPhotosSeries_CollectionChanged;
}
private void _dropPhotosSeries_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(new PropertyChangedEventArgs(nameof(CanDrawPlot)));
CurrentUser.OnPropertyChanged(new PropertyChangedEventArgs(nameof(User.IsAnySelectedSeriesCanDrawPlot)));
}
public Guid SeriesId { get; set; }
private ObservableCollection<DropPhoto> _dropPhotosSeries;
public ObservableCollection<DropPhoto> DropPhotosSeries
{
get
{
return _dropPhotosSeries;
}
set
{
_dropPhotosSeries = value;
OnPropertyChanged(new PropertyChangedEventArgs("DropPhotosSeries"));
}
}
private ReferencePhoto _referencePhotoForSeries;
public ReferencePhoto ReferencePhotoForSeries
{
get
{
return _referencePhotoForSeries;
}
set
{
_referencePhotoForSeries = value;
OnPropertyChanged(new PropertyChangedEventArgs("ReferencePhotoForSeries"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(IntervalBetweenPhotos))
OnPropertyChanged(new PropertyChangedEventArgs(nameof(CanDrawPlot)));
if (e.PropertyName == nameof(IsChecked))
CurrentUser.OnPropertyChanged(new PropertyChangedEventArgs(nameof(User.IsAnySelectedSeriesCanDrawPlot))); ;
PropertyChanged?.Invoke(this, e);
}
}
public class ReferencePhoto : INotifyPropertyChanged
{
private Series _series;
public Series Series
{
get
{
return _series;
}
set
{
_series = value;
OnPropertyChanged(new PropertyChangedEventArgs("Series"));
}
}
public Guid ReferencePhotoId { get; set; }
private SimpleLine _simpleLine;
public SimpleLine SimpleLine
{
get
{
return _simpleLine;
}
set
{
_simpleLine = value;
OnPropertyChanged(new PropertyChangedEventArgs("SimpleLine"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChanged?.Invoke(this, e);
}
}
public class DropPhoto : INotifyPropertyChanged
{
private Guid _currentSeriesId;
public Guid CurrentSeriesId
{
get
{
return _currentSeriesId;
}
set
{
_currentSeriesId = value;
OnPropertyChanged(new PropertyChangedEventArgs("CurrentSeriesId"));
}
}
private Series _currentSeries;
public Series CurrentSeries
{
get
{
return _currentSeries;
}
set
{
_currentSeries = value;
OnPropertyChanged(new PropertyChangedEventArgs("CurrentSeries"));
}
}
public Guid DropPhotoId { get; set; }
private SimpleLine _simpleHorizontalLine;
public SimpleLine SimpleHorizontalLine
{
get
{
return _simpleHorizontalLine;
}
set
{
_simpleHorizontalLine = value;
OnPropertyChanged(new PropertyChangedEventArgs("SimpleHorizontalLine"));
}
}
private SimpleLine _simpleVerticalLine;
public SimpleLine SimpleVerticalLine
{
get
{
return _simpleVerticalLine;
}
set
{
_simpleVerticalLine = value;
OnPropertyChanged(new PropertyChangedEventArgs("SimpleVerticalLine"));
}
}
private Drop _drop;
public Drop Drop
{
get
{
return _drop;
}
set
{
_drop = value;
OnPropertyChanged(new PropertyChangedEventArgs("Drop"));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
PropertyChanged?.Invoke(this, e);
}
}
public class SimpleLine
{
public Guid SimpleLineId { get; set; }
public ReferencePhoto ReferencePhoto { get; set; }
public DropPhoto DropPhotoHorizontalLine { get; set; }
public DropPhoto DropPhotoVerticalLine { get; set; }
}
Например, мне нужно создать новую Серии. Мое приложение реализует шаблон хранилища. Метод создания серий выглядит следующим образом:
public async Task CreateSeries(DbSeries series)
{
using (var context = new DDropContext())
{
var createdSeries = context.Series.Add(series);
await context.SaveChangesAsync();
}
}
Сначала я создаю новую серию:
Series seriesToAdd = new Series()
{
SeriesId = Guid.NewGuid(),
Title = seriesTitle,
AddedDate = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss"),
ReferencePhotoForSeries = new ReferencePhoto()
{
ReferencePhotoId = Guid.NewGuid(),
Series = CurrentSeries,
SimpleLine = new SimpleLine { SimpleLineId = Guid.NewGuid()}
},
CurrentUser = User,
CurrentUserId = User.UserId
};
Затем мне нужно сопоставить ее с DbSeries и создать новую DbSeries:
try
{
await _dDropRepository.CreateSeries(DDropDbEntitiesMapper.SingleSeriesToSingleDbSeries(seriesToAdd, User));
}
catch (Exception)
{
}
Чтобы отобразить Series в DbSeries, я использую очень сложное средство отображения, которое не работает должным образом:
public static DbSeries SingleSeriesToSingleDbSeries(Series userSeries, User user)
{
DbSeries singleSeries = new DbSeries();
List<DbDropPhoto> dropPhotosSeries = new List<DbDropPhoto>();
foreach (var dropPhoto in userSeries.DropPhotosSeries)
{
DbDropPhoto newDbDropPhoto = new DbDropPhoto()
{
Name = dropPhoto.Name,
Content = dropPhoto.Content,
AddedDate = dropPhoto.AddedDate,
DropPhotoId = dropPhoto.DropPhotoId,
XDiameterInPixels = dropPhoto.XDiameterInPixels,
YDiameterInPixels = dropPhoto.YDiameterInPixels,
ZDiameterInPixels = dropPhoto.ZDiameterInPixels,
CurrentSeries = SingleSeriesToSingleDbSeries(userSeries, user),
CurrentSeriesId = userSeries.SeriesId,
};
DbSimpleLine newHorizontalDbSimpleLine = new DbSimpleLine
{
X1 = dropPhoto.SimpleHorizontalLine.X1,
X2 = dropPhoto.SimpleHorizontalLine.X2,
Y1 = dropPhoto.SimpleHorizontalLine.Y1,
Y2 = dropPhoto.SimpleHorizontalLine.Y2,
DropPhotoHorizontalLine = newDbDropPhoto,
SimpleLineId = dropPhoto.SimpleHorizontalLine.SimpleLineId,
};
DbSimpleLine newVerticalDbSimpleLine = new DbSimpleLine
{
X1 = dropPhoto.SimpleVerticalLine.X1,
X2 = dropPhoto.SimpleVerticalLine.X2,
Y1 = dropPhoto.SimpleVerticalLine.Y1,
Y2 = dropPhoto.SimpleVerticalLine.Y2,
DropPhotoVerticalLine = newDbDropPhoto,
SimpleLineId = dropPhoto.SimpleHorizontalLine.SimpleLineId,
};
DbDrop newDbDrop = new DbDrop()
{
DropId = dropPhoto.Drop.DropId,
RadiusInMeters = dropPhoto.Drop.RadiusInMeters,
VolumeInCubicalMeters = dropPhoto.Drop.VolumeInCubicalMeters,
XDiameterInMeters = dropPhoto.Drop.XDiameterInMeters,
YDiameterInMeters = dropPhoto.Drop.YDiameterInMeters,
ZDiameterInMeters = dropPhoto.Drop.ZDiameterInMeters,
DropPhoto = newDbDropPhoto,
};
newDbDropPhoto.Drop = newDbDrop;
newDbDropPhoto.SimpleHorizontalLine = newHorizontalDbSimpleLine;
newDbDropPhoto.SimpleVerticalLine = newVerticalDbSimpleLine;
dropPhotosSeries.Add(newDbDropPhoto);
}
if (userSeries.ReferencePhotoForSeries != null)
{
var referencePhoto = new DbReferencePhoto
{
Content = userSeries.ReferencePhotoForSeries.Content,
Name = userSeries.ReferencePhotoForSeries.Name,
PixelsInMillimeter = userSeries.ReferencePhotoForSeries.PixelsInMillimeter,
ReferencePhotoId = userSeries.ReferencePhotoForSeries.ReferencePhotoId,
Series = singleSeries,
};
var simpleLineForReferencePhoto = new DbSimpleLine
{
X1 = userSeries.ReferencePhotoForSeries.SimpleLine.X1,
X2 = userSeries.ReferencePhotoForSeries.SimpleLine.X2,
Y1 = userSeries.ReferencePhotoForSeries.SimpleLine.Y1,
Y2 = userSeries.ReferencePhotoForSeries.SimpleLine.Y2,
ReferencePhoto = referencePhoto,
SimpleLineId = userSeries.ReferencePhotoForSeries.SimpleLine.SimpleLineId,
};
referencePhoto.SimpleLine = simpleLineForReferencePhoto;
singleSeries.ReferencePhotoForSeries = referencePhoto;
}
singleSeries.DropPhotosSeries = dropPhotosSeries;
singleSeries.IntervalBetweenPhotos = userSeries.IntervalBetweenPhotos;
singleSeries.AddedDate = userSeries.AddedDate;
singleSeries.SeriesId = userSeries.SeriesId;
singleSeries.Title = userSeries.Title;
singleSeries.CurrentUser = UserToDbUser(user);
singleSeries.CurrentUserId = user.UserId;
return singleSeries;
}
Основная проблема заключается в том, что в DbSeries есть publi c DbUser CurrentUser, поэтому, когда я сопоставить Series с DbSeries. Мне нужно заполнить его User, чтобы я преобразовал его в DbUser, что приводит к исключению stackoverflow (сам метод SingleSeriesToSingleDbSeries вызывает). Есть ли лучший способ достичь моей цели?