以下のようなモデル/データベーステーブルがあると仮定しましょう(うまくレイアウトされていませんが、私の質問に適合します)。また、1 つの映画には常に 1 人の監督と 1 人のプロデューサーしかいないと仮定しましょう。
ジャンル
- ID
- 名前
サブジャンル
- ID
- 名前
- ジャンルID
- ジャンル(航海財産)
監督
- ID
- 名前
List<Movie>
(航行財産)
プロデューサー
- ID
- 名前
List<Movie>
(航行財産)
アクター
- ID
- 名前
List<Movie>
(データベースに多対多テーブルがあります) (ナビゲーション プロパティ)
映画
- ID
- 名前
- サブジャンルID
- ディレクター ID
- プロデューサー ID
List<Actor>
(航行財産)- ディレクター(航海財産)
- プロデューサー(航海財産)
- SubGenre (ナビゲーション プロパティ)
MovieActors (テーブル)
- ムービー ID
- アクター ID
ここで、すでにデータ レイヤーにいると仮定しましょう (したがって、ID 以外のオブジェクトには主要な変更追跡はありません)。永続化する必要があるデータが movie オブジェクトにあります。存在する場合は更新する必要があり、挿入されていない場合は更新する必要があります。
DataLayer に送信されるムービー オブジェクト (movieDTO)。
- ムービー名
- ジャンル名
- サブジャンル名
- ディレクター名
- プロデューサー名
- ActorNames の一覧表示
また、何百万もの監督/プロデューサー/俳優/映画 (基本的に各テーブルには膨大な量のデータ) があり、簡単にするために監督/プロデューサー/俳優/映画の名前は一意であると仮定します。したがって、ロジックは、SubGenre が存在する場合はそれを使用し、そうでない場合は SubGenre レコードを作成します。同様に、Genre が存在する場合は探し、そうでない場合はそれを使用して作成します。監督、プロデューサー、俳優についても同様です。
最後に、質問は
- これらのうちどれがより高速で、その理由は何ですか? (または) 数百万のレコードを考慮しても同じですか?
- Sql Server と Oracle の間で変更される可能性はありますか? (オラクルでは、プロバイダーとして Devart を使用しています)
アプローチ 1:
using (MovieDBContext context = new MovieDBContext())
{
Movie movie;
movie = context.Movies.Where(a => a.Name == movieDTO.MovieName).SingleOrDefault();
if (movie == null)
movie = new Movie() { Name = movieDTO.MovieName };
var subGenre = context.SubGenres.Where(a => a.Name == movieDTO.SubGenreName).SingleOrDefault();
if (subGenre == null)
{
movie.SubGenre = new SubGenre() { Name = movieDTO.SubGenreName };
// Check if Genre exists.
var genre = context.Genres.Where(a => a.Name == movieDTO.GenreName).SingleOrDefault();
if (genre == null)
{
movie.SubGenre.Genre = new Genre() { Name = movieDTO.GenreName };
}
else
{
movie.SubGenre.Genre = genre;
}
}
else
movie.SubGenre = subGenre;
var director = context.Directors.Where(a => a.Name == movieDTO.DirectorName).SingleOrDefault();
if (director == null)
movie.Director = new Director() { Name = movieDTO.DirectorName };
else
movie.Director = director;
var producer = context.Producers.Where(a => a.Name == movieDTO.ProducerName).SingleOrDefault();
if (producer == null)
movie.Producer = new Producer() { Name = movieDTO.ProducerName };
else
movie.Producer = producer;
// I am skipping the logic of deleting all the actors if the movie is existing.
foreach (var name in movieDTO.Actors)
{
var actor = context.Actors.Where(a => a.Name == name).SingleOrDefault();
if (actor == null)
movie.Actors.Add(new Actor() { Name = name });
else
movie.Actors.Add(actor);
}
// Finally save changes. All the non-existing entities are added at once.
// EF is keeping track if the entity exists or not.
context.SaveChanges();
}
アプローチ 2:
using (MovieDBContext context = new MovieDBContext())
{
var genre = context.Genres.Where(a => a.Name == movieDTO.GenreName).SingleOrDefault();
if (genre == null)
{
genre = new Genre() { Name = movieDTO.GenreName };
context.Genres.Add(genre); // genre.Id is populated with the new id.
context.SaveChanges();
}
var subGenre = context.SubGenre.Where(a => a.Name == movieDTO.SubGenreName).SingleOrDefault();
if (subGenre == null)
{
subGenre = new SubGenre() { Name = movieDTO.SubGenreName };
context.SubGenres.Add(subGenre); // subGenre.Id is populated with the new id.
context.SaveChanges();
}
var director = context.Directors.Where(a => a.Name == movieDTO.DirectorName).SingleOrDefault();
if (director == null)
{
director = new Director() { Name = movieDTO.DirectorName };
context.Directors.Add(director); // director.Id is populated with the new id.
context.SaveChanges();
}
var producer = context.Producers.Where(a => a.Name == movieDTO.ProducerName).SingleOrDefault();
if (producer == null)
{
producer = new Producer() { Name = movieDTO.ProducerName };
context.Producers.Add(producer); // director.Id is populated with the new id.
context.SaveChanges();
}
// Similarly for actors, add them if they don't exist.
foreach (var name in movieDTO.Actors)
{
var actor = new Actor() { Name = movieDTO.name };
context.Actors.Add(actor);
context.SaveChanges();
}
// Lastly movie.
Movie movie = context.Movies.Where(a => a.Name == movieDTO.MovieName).SingleOrDefault();
if (movie == null)
{
movie = new Movie() { Name = movieDTO.MovieName };
}
// This works for update as well.
// The id's are added/updated instead of actual entities.
movie.DirectorId = director.Id;
movie.SubGenreId = subGenre.Id;
movie.ProducerId = producer.Id;
// I am skipping the logic of deleting all the actors if the movie is existing.
foreach (var name in movieDTO.Actors)
{
var actor = context.Actors.Where(a => a.Name == name).SingleOrDefault(); // Actors always exist now because we added them above.
movie.Actors.Add(actor);
}
// Finally save changes. Here only Movie object is saved as all other objects are saved earlier.
context.SaveChanges();
}