public void Deleting_Principal_With_Include_Will_Remove_Dependent() { // Populate data using (var context = new OtmContext(ContextOptions, IsRequired)) { context.Blogs.AddRange(GenerateData()); context.SaveChanges(); } // Update post through its principal using (var context = new OtmContext(ContextOptions, IsRequired)) { var blog = context.Blogs.Include(b => b.Posts).FirstOrDefault(b => b.Url == "https://timheuer.com/blog/"); Assert.IsNotNull(blog); context.Blogs.Remove(blog); context.SaveChanges(); } using (var context = new OtmContext(ContextOptions, IsRequired)) { // Blog is removed var blog = context.Blogs.FirstOrDefault(b => b.Url == "https://timheuer.com/blog/"); Assert.IsNull(blog); // Post IS REMOVED var post = context.Posts.FirstOrDefault(p => p.Title.Contains("Deploying .NET Core 3")); Assert.IsNull(post); } }
public void Deleting_DEPENDENT_Has_No_Effect_On_Principal() { // Populate data using (var context = new OtmContext(ContextOptions, IsRequired)) { context.Blogs.AddRange(GenerateData()); context.SaveChanges(); } // Update post through its principal using (var context = new OtmContext(ContextOptions, IsRequired)) { var post = context.Posts.FirstOrDefault(p => p.Title.Contains("Deploying .NET Core 3")); Assert.IsNotNull(post); context.Posts.Remove(post); context.SaveChanges(); } using (var context = new OtmContext(ContextOptions, IsRequired)) { // Post is deleted var post = context.Posts.FirstOrDefault(p => p.Title.Contains("Deploying .NET Core 3")); Assert.IsNull(post); // PRincipal not removed var blog = context.Blogs.FirstOrDefault(b => b.Url == "https://timheuer.com/blog/"); Assert.IsNotNull(blog); } }
public void Can_Update_Dependent_Alone() { // Populate data using (var context = new OtmContext(ContextOptions, IsRequired)) { context.Blogs.AddRange(GenerateData()); context.SaveChanges(); } // Update post through its principal using (var context = new OtmContext(ContextOptions, IsRequired)) { var post = context.Posts.FirstOrDefault(p => p.Title.Contains("Deploying .NET Core 3")); Assert.IsNotNull(post); post.Title = "Deploying .NET 5 apps as self-contained"; context.SaveChanges(); } using (var context = new OtmContext(ContextOptions, IsRequired)) { var post = context.Posts.FirstOrDefault(p => p.Title.Contains("Deploying .NET 5 apps")); Assert.IsNotNull(post); } }
public void Deleting_Principal_Will_Remove_Dependent() { // Populate data using (var context = new OtmContext(ContextOptions, IsRequired)) { context.Blogs.AddRange(GenerateData()); context.SaveChanges(); } // Update post through its principal using (var context = new OtmContext(ContextOptions, IsRequired)) { var blog = context.Blogs.FirstOrDefault(b => b.Url == "https://timheuer.com/blog/"); Assert.IsNotNull(blog); context.Blogs.Remove(blog); context.SaveChanges(); } // Dependent entities are removed using (var context = new OtmContext(ContextOptions, IsRequired)) { var blog = context.Blogs.FirstOrDefault(b => b.Url == "https://timheuer.com/blog/"); Assert.IsNull(blog); var post1 = context.Posts.FirstOrDefault(p => p.Title == "Deploying .NET Core 3 apps as self-contained"); Assert.IsNull(post1); var post2 = context.Posts.FirstOrDefault(p => p.Title == "Skipping CI in GitHub Actions Workflows"); Assert.IsNull(post2); } }
public void Can_Update_Dependent_Through_Principal_With_Include() { // Populate data using (var context = new OtmContext(ContextOptions, IsRequired)) { context.Blogs.AddRange(GenerateData()); context.SaveChanges(); } // Update post through its principal using (var context = new OtmContext(ContextOptions, IsRequired)) { var blog = context.Blogs.Include(b => b.Posts).FirstOrDefault(b => b.Url == "https://timheuer.com/blog/"); Assert.IsNotNull(blog); Assert.IsNotNull(blog.Posts); var post = blog.Posts.FirstOrDefault(p => p.Title.Contains("Deploying .NET Core 3")); Assert.IsNotNull(post); post.Title = "Deploying .NET 5 apps as self-contained"; context.SaveChanges(); } using (var context = new OtmContext(ContextOptions, IsRequired)) { var post = context.Posts.FirstOrDefault(p => p.Title.Contains("Deploying .NET 5 apps")); Assert.IsNotNull(post); } }
public void Deleting_Principal_With_Include_SUCCEED_Has_No_Effect_On_Dependent() { // Populate data using (var context = new OtmContext(ContextOptions, IsRequired)) { context.Blogs.AddRange(GenerateData()); context.SaveChanges(); } // Update post through its principal using (var context = new OtmContext(ContextOptions, IsRequired)) { var blog = context.Blogs.Include(b => b.Posts).FirstOrDefault(b => b.Url == "https://timheuer.com/blog/"); Assert.IsNotNull(blog); context.Blogs.Remove(blog); context.SaveChanges(); } using (var context = new OtmContext(ContextOptions, IsRequired)) { // Blog is removed var blog = context.Blogs.FirstOrDefault(b => b.Url == "https://timheuer.com/blog/"); Assert.IsNull(blog); // Post still alive var post = context.Posts.FirstOrDefault(p => p.Title.Contains("Deploying .NET Core 3")); Assert.IsNotNull(post); var post2 = context.Posts.FirstOrDefault(p => p.Title == "Skipping CI in GitHub Actions Workflows"); Assert.IsNotNull(post2); } }
public void Can_NOT_Create_Dependent_Without_Principal() { using (var context = new OtmContext(ContextOptions, IsRequired)) { var post = new Post { Title = "Test Post", Content = "No content" }; context.Posts.Add(post); Assert.That(() => context.SaveChanges(), Throws.Exception); } }
public void Can_Create_Principal_Without_Dependent() { using (var context = new OtmContext(ContextOptions, IsRequired)) { var blog = new Blog { Url = "https://medium.com/@bc" }; context.Blogs.Add(blog); context.SaveChanges(); } using (var context = new OtmContext(ContextOptions, IsRequired)) { var blog = context.Blogs.FirstOrDefault(b => b.Url == "https://medium.com/@bc"); Assert.IsNotNull(blog); } }
public void Can_Create_Dependent_Without_Principal() { using (var context = new OtmContext(ContextOptions, IsRequired)) { var post = new Post { Title = "Test Post", Content = "No content" }; context.Posts.Add(post); context.SaveChanges(); } using (var context = new OtmContext(ContextOptions, IsRequired)) { var post = context.Posts.FirstOrDefault(p => p.Title == "Test Post"); Assert.IsNotNull(post); } }
public void Deleting_Principal_FAILS_Without_Including_Dependent() { // Populate data using (var context = new OtmContext(ContextOptions, IsRequired)) { context.Blogs.AddRange(GenerateData()); context.SaveChanges(); } // Delete fails for principal entity because it needs to have navigation property loaded to set FK to NULL. using (var context = new OtmContext(ContextOptions, IsRequired)) { var blog = context.Blogs.FirstOrDefault(b => b.Url == "https://timheuer.com/blog/"); Assert.IsNotNull(blog); context.Blogs.Remove(blog); Assert.That(() => context.SaveChanges(), Throws.Exception); } }
public void Can_NOT_Update_Dependent_Through_Principal_Without_Include() { // Populate data using (var context = new OtmContext(ContextOptions, IsRequired)) { context.Blogs.AddRange(GenerateData()); context.SaveChanges(); } // Update post through its principal using (var context = new OtmContext(ContextOptions, IsRequired)) { var blog = context.Blogs.FirstOrDefault(b => b.Url == "https://timheuer.com/blog/"); Assert.IsNotNull(blog); // Since it is initialized by default, dependent is not null Assert.IsNotNull(blog.Posts); Assert.AreEqual(0, blog.Posts.Count); } }
public void Can_Create_Dependent_With_Principal_Only() { using (var context = new OtmContext(ContextOptions, IsRequired)) { var post = new Post { Title = "Test Post", Content = "No content", Blog = new Blog { Url = "https://medium.com" } }; context.Posts.Add(post); context.SaveChanges(); } using (var context = new OtmContext(ContextOptions, IsRequired)) { var post = context.Posts.Include(p => p.Blog).FirstOrDefault(p => p.Title == "Test Post"); Assert.IsNotNull(post); Assert.IsNotNull(post.Blog); } }
public static void Run(DbContextOptions options, bool isRequired = false) { Console.WriteLine("----- CREATE -----"); using (var context = new OtmContext(options, isRequired)) { context.Database.EnsureDeleted(); context.Database.EnsureCreated(); // Console.Write("Creating a new blog w/o posts"); var blog1 = new Blog { Url = "http://blogs.msdn.com/adonet" }; context.Blogs.Add(blog1); context.SaveChanges(); Console.WriteLine("==> Done."); Console.Write("Creating a new blog with posts"); var blog2 = new Blog { Url = "https://wordpress.com" }; blog2.Posts.AddRange( new List <Post> { new Post { Title = "My first app", Content = "I wrote an app using EF Core 1" }, new Post { Title = "My second app", Content = "I wrote an app using EF Core 2" } }); context.Blogs.Add(blog2); context.SaveChanges(); Console.WriteLine("==> Done"); // Console.Write("Creating post w/o blog"); var post3 = new Post { Title = "EF Core Tutorial", Content = "Getting started with EF Core" }; context.Posts.Add(post3); try { context.SaveChanges(); Console.WriteLine("==> Done"); } catch (Exception) { context.Entry(post3).State = EntityState.Detached; context.Posts.Remove(post3); Console.WriteLine("==> FAILED: Can not save post w/o blog. Provide a required relationship."); } // Console.Write("Creating a post w/ blog"); var post4 = new Post { Title = "Swift tutorial", Content = "Learn how to code Swift.", Blog = new Blog { Url = "https://medium.com/@bc/swift" } }; context.Posts.Add(post4); try { context.SaveChanges(); Console.WriteLine("==> Done"); } catch (Exception) { context.Entry(post4).State = EntityState.Detached; context.Posts.Remove(post4); Console.WriteLine("==>FAILED: Can not save the post w/ blog"); } } Console.WriteLine("----- QUERY -----"); using (var context = new OtmContext(options, isRequired)) { Console.Write("Querying for a blog w/o post"); var foundBlog1 = context.Blogs.First(b => b.Url == "http://blogs.msdn.com/adonet"); if (foundBlog1 != null) { Console.WriteLine("==> Done: Blog1 with Url{0} found", "http://blogs.msdn.com/adonet"); } else { Console.WriteLine("==> Failed: Can not find Blog with Url: {0}", "http://blogs.msdn.com/adonet"); } // Console.Write("Querying for a blog w posts"); var foundBlog2 = context.Blogs.FirstOrDefault(b => b.Url == "https://wordpress.com"); if (foundBlog2 == null) { Console.WriteLine("Not found. Querying with .Include() method."); foundBlog2 = context.Blogs.Include(b => b.Posts).FirstOrDefault(b => b.Url == "https://wordpress.com"); } Console.WriteLine("==> Done: Blog w/ Posts with Url{0} found", foundBlog2.Url); // Console.Write("Querying for post w/o blog"); var foundPost1 = context.Posts.FirstOrDefault(p => p.Title == "EF Core Tutorial"); if (foundPost1 != null) { Console.WriteLine("==> Done: Post w/ blog is found. Title: {0}", foundPost1.Title); } else { Console.WriteLine("==> Failed: Can not find post w/ blog."); } // Console.Write("Querying for a post w blog"); var foundPost2 = context.Posts.FirstOrDefault(p => p.Blog.Url == "https://medium.com/@bc/swift"); if (foundPost2 == null) { Console.WriteLine("Can not find the post w/ blog. Using .Include()"); foundPost2 = context.Posts.Include(p => p.Blog).FirstOrDefault(p => p.Blog.Url == "https://medium.com/@bc/swift"); } Console.WriteLine("==> Done: Post w blog is found"); } Console.WriteLine("----- UPDATE -----"); using (var context = new OtmContext(options, isRequired)) { Console.Write("Update a blog w/o post by adding a post"); var foundBlog1 = context.Blogs.FirstOrDefault(b => b.Url == "http://blogs.msdn.com/adonet"); foundBlog1.Posts.Add( new Post { Title = "How to create Hello, World app in C++", Content = "This is a very very long story" } ); context.SaveChanges(); Console.Write("==>Done"); Console.Write("Update a blog's post"); // Need to include navigation property var foundBlog2 = context.Blogs.Include(b => b.Posts).FirstOrDefault(b => b.Url == "https://wordpress.com"); foundBlog2.Posts.Add(new Post { Title = "Smart pointers in C++", Content = "Smart pointers are sometimes life-savers...." }); context.SaveChanges(); Console.WriteLine("==> Done"); Console.Write("Updating a post w/o blog by adding a blog"); var foundPost1 = context.Posts.FirstOrDefault(p => p.Title == "EF Core Tutorial"); if (foundPost1 == null) { Console.WriteLine("==> FAILED: Can not find the post w/o a blog record. Make sure the relationship is optional"); } else { foundPost1.Blog = new Blog { Url = "https://medium.com/@someone/do-coding" }; context.SaveChanges(); Console.WriteLine("==> Done: Post w/o blog is found and updated"); } Console.Write("Updating a post w/ blog"); var foundPost2 = context.Posts.Include(p => p.Blog).FirstOrDefault(p => p.Blog.Url == "https://medium.com/@bc/swift"); if (foundPost2 == null) { Console.WriteLine("==> FAILED: Can not find a post w/ blog Url: {0}", "https://medium.com/@bc/swift"); } else { foundPost2.Title = "Do some Swift stuff"; context.SaveChanges(); Console.WriteLine("==> Done: The post w/ blog is found and updated"); } } Console.WriteLine("----- DELETE -----"); using (var context = new OtmContext(options, isRequired)) { // Delete Console.Write("Delete a blog w/ post"); var foundBlog = context.Blogs.Include(b => b.Posts).FirstOrDefault(b => b.Posts.Any(p => p.Title == "How to create Hello, World app in C++")); if (foundBlog == null) { Console.WriteLine("==>FAILED: Can not find a blog w/ post titled: {0}", "How to create Hello, World app in C++"); } else { // this will remove the dependent posts if the relationship is required. context.Blogs.Remove(foundBlog); context.SaveChanges(); Console.WriteLine("==> Done: Blog is removed"); } Console.Write("Delete a post w/blog"); // since post is dependent, it does not affect its principal entity var foundPost = context.Posts.FirstOrDefault(p => p.Title == "My first app"); if (foundPost == null) { Console.WriteLine("==> Can not find a post w/ blog titled My first app"); } else { context.Posts.Remove(foundPost); context.SaveChanges(); Console.WriteLine("==> Done: The post titled My first app is removed from the database"); } } }