Skip to content

Commit

Permalink
📝 Saving Data
Browse files Browse the repository at this point in the history
Initial cut of "Saving Data" section of docs/index.rst
 - basic saving
 - cascade delete
 - explicit values in generated columns
  • Loading branch information
rowanmiller committed Feb 10, 2016
1 parent 851adfa commit 6bb7689
Show file tree
Hide file tree
Showing 25 changed files with 786 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Entity Framework Documentation
platforms/index
providers/index
modeling/index
saving/index
cli/index
miscellaneous/index

Expand Down
3 changes: 3 additions & 0 deletions docs/miscellaneous/logging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Logging
.. contents:: `In this article:`
:local:

.. include:: /_shared/sample.txt
.. _sample: https://github.com/aspnet/EntityFramework.Docs/tree/master/docs/miscellaneous/logging/sample

Create a logger
---------------

Expand Down
63 changes: 63 additions & 0 deletions docs/saving/basic.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
Basic Save
==========

Learn how to add, modify, and remove data using your context and entity classes.

.. contents:: `In this article:`
:depth: 2
:local:

.. include:: /_shared/sample.txt
.. _sample: https://github.com/aspnet/EntityFramework.Docs/tree/master/docs/saving/sample/EFSaving/Basics/

ChangeTracker & SaveChanges
---------------------------

Each context instance has a `ChangeTracker` that is responsible for keeping track of changes that need to be written to the database. As you make changes to instances of your entity classes, these changes are recorded in the `ChangeTracker` and then written to the database when you call `SaveChanges`.

Adding Data
-----------

Use the `DbSet.Add` method to add new instances of your entity classes. The data will be inserted in the database when you call `SaveChanges`.

.. literalinclude:: sample/EFSaving/Basics/Sample.cs
:language: c#
:lines: 17-24
:linenos:

Updating Data
-------------

EF will automatically detect changes made to an existing entity that is tracked by the context. This includes entities that you load/query from the database, and entities that were previously added and saved to the database.

Simply modify the values assigned to properties and then call `SaveChanges`.

.. literalinclude:: sample/EFSaving/Basics/Sample.cs
:language: c#
:lines: 26-31
:linenos:

Deleting Data
-------------

Use the `DbSet.Remove` method to delete instances of you entity classes.

If the entity already exists in the database, it will be deleted during `SaveChanges`. If the entity has not yet been saved to the database (i.e. it is tracked as added) then it will be removed from the context and will no longer be inserted when `SaveChanges` is called.

.. literalinclude:: sample/EFSaving/Basics/Sample.cs
:language: c#
:lines: 33-38
:linenos:

Multiple Operations in a single SaveChanges
-------------------------------------------

You can combine multiple Add/Update/Remove operations into a single call to `SaveChanges`.

.. note::
For most database providers, `SaveChanges` is transactional. This means all the operations will either succeed or fail and the operations will never be left partially applied.

.. literalinclude:: sample/EFSaving/Basics/Sample.cs
:language: c#
:lines: 48-60
:linenos:
59 changes: 59 additions & 0 deletions docs/saving/cascade-delete.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
Cascade Delete
==============

Cascade delete allows deletion of a principal/parent entity to have a side effect on dependent/child entities it is related to.

There are three cascade delete behaviors:
* **Cascade:** Dependent entities are also deleted.
* **SetNull:** The foreign key properties in dependent entities are set to null.
* **Restrict:** The delete operation is not applied to dependent entities. The dependent entities remain unchanged.

See :doc:`/modeling/relationships` for more information about conventions and configuration for cascade delete.

.. contents:: `In this article:`
:local:

.. include:: /_shared/sample.txt
.. _sample: https://github.com/aspnet/EntityFramework.Docs/tree/master/docs/saving/sample/EFSaving/CascadeDelete/

Cascading to tracked entities
-----------------------------

When you call `SaveChanges`, the cascade delete rules will be applied to any entities that are being tracked by the context.

Consider a simple `Blog` and `Post` model where the relationship between the two entities is required. By convention. the cascade behavior for this relationship is set to `Cascade`.

The following code loads a Blog and all its related Posts from the database (using the `Include` method). The code then deletes the Blog.

.. literalinclude:: sample/EFSaving/CascadeDelete/Sample.cs
:language: c#
:lines: 30-35
:linenos:

Because all the Posts are tracked by the context, the cascade behavior is applied to them before saving to the database. EF therefore issues a `DELETE` statement for each entity.

::

DELETE FROM [Post]
WHERE [PostId] = @p0;
DELETE FROM [Post]
WHERE [PostId] = @p1;
DELETE FROM [Blog]
WHERE [BlogId] = @p2;

Cascading to untracked entities
-------------------------------

The following code is almost the same as our previous example, except it does not load the related Posts from the database.

.. literalinclude:: sample/EFSaving/CascadeDelete/Sample.cs
:language: c#
:lines: 52-57
:linenos:

Because the Posts are not tracked by the context, a `DELETE` statement is only issued for the `Blog`. This relies on a corresponding cascade behavior being present in the database to ensure data that is not tracked by the context is also deleted. If you use EF to create the database, this cascade behavior will be setup for you.

::

DELETE FROM [Blog]
WHERE [BlogId] = @p0;
6 changes: 6 additions & 0 deletions docs/saving/disconnected-entities.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
|stub-icon| Disconnected Entities
=================================

.. include:: /_shared/stub-topic.txt
.. include:: /_shared/stub-notice.txt
.. _issue: https://github.com/aspnet/EntityFramework.Docs/issues/126
71 changes: 71 additions & 0 deletions docs/saving/explicit-values-generated-properties.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
Setting explicit values for generated properties
================================================

A generated property is a property whose value is generated (either by EF or the database) when the entity is added and/or updated. See :doc:`/modeling/generated-properties` for more information.

There may be situations where you want to set an explicit value for a generated property, rather than having one generated.

.. contents:: `In this article:`
:depth: 2
:local:

.. include:: /_shared/sample.txt
.. _sample: https://github.com/aspnet/EntityFramework.Docs/tree/master/docs/saving/sample/EFSaving/ExplicitValuesGenerateProperties/

The model
---------

The model used in this article contains a single ``Employee`` entity.

.. literalinclude:: sample/EFSaving/ExplicitValuesGenerateProperties/Employee.cs
:language: c#
:lines: 5-10
:linenos:

The context is setup to target SQL Server:
* By convention the ``Employee.EmployeeId`` property will be a store generated ``IDENTITY`` column
* The ``Employee.EmploymentStarted`` property has also been setup to have values generated by the database for new entities

.. literalinclude:: sample/EFSaving/ExplicitValuesGenerateProperties/EmployeeContext.cs
:language: c#
:lines: 5-20
:linenos:

Saving an explicit value during add
-----------------------------------

In the following code, two employees are being inserted into the database
* For the first, no value is assigned to ``Employee.EmploymentStarted`` property, so it remains set to the CLR default value for ``DateTime``.
* For the second, we have set an explicit value of ``1-Jan-2000``.

.. literalinclude:: sample/EFSaving/ExplicitValuesGenerateProperties/Sample.cs
:language: c#
:lines: 16-26
:linenos:
:emphasize-lines: 4

The code results in the following output, showing that the database generated a value for the first employee and our explicit value was used for the second::

1: John Doe, 1/28/2016 12:00:00 AM
2: Jane Doe, 1/1/2000 12:00:00 AM


Explicit values into SQL Server IDENTITY columns
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

For most situations, the approach shown above will work for key properties. However, to insert explicit values into a SQL Server ``IDENTITY`` column, you need to manually enable ``IDENTITY_INSERT`` before calling ``SaveChanges()``.

.. note::
We have a `feature request <https://github.com/aspnet/EntityFramework/issues/703>`_ on our backlog to do this automatically within the SQL Server provider.

.. literalinclude:: sample/EFSaving/ExplicitValuesGenerateProperties/Sample.cs
:language: c#
:lines: 34-56
:linenos:
:emphasize-lines: 6-16

Setting an explicit values during update
----------------------------------------

.. caution::
Due to various bugs, this scenario is not properly supported in the current pre-release of EF Core. See `documentation issue #122 <https://github.com/aspnet/EntityFramework.Docs/issues/122>`_ for more details.
14 changes: 14 additions & 0 deletions docs/saving/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Saving Data
===========

The following articles are available

.. toctree::
:titlesonly:
:maxdepth: 1

basic
related-data
cascade-delete
disconnected-entities
explicit-values-generated-properties
6 changes: 6 additions & 0 deletions docs/saving/related-data.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
|stub-icon| Related Data
========================

.. include:: /_shared/stub-topic.txt
.. include:: /_shared/stub-notice.txt
.. _issue: https://github.com/aspnet/EntityFramework.Docs/issues/126
22 changes: 22 additions & 0 deletions docs/saving/sample/EFSaving.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFSaving", "EFSaving\EFSaving.csproj", "{353F06F1-F0E0-4A8F-83AA-7115CD05832D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{353F06F1-F0E0-4A8F-83AA-7115CD05832D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{353F06F1-F0E0-4A8F-83AA-7115CD05832D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{353F06F1-F0E0-4A8F-83AA-7115CD05832D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{353F06F1-F0E0-4A8F-83AA-7115CD05832D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
6 changes: 6 additions & 0 deletions docs/saving/sample/EFSaving/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
</configuration>
12 changes: 12 additions & 0 deletions docs/saving/sample/EFSaving/Basics/Blog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Collections.Generic;

namespace EFSaving.Basics
{
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }

public List<Post> Posts { get; set; }
}
}
15 changes: 15 additions & 0 deletions docs/saving/sample/EFSaving/Basics/BloggingContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Microsoft.Data.Entity;

namespace EFSaving.Basics
{
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFSaving.Basics;Trusted_Connection=True;");
}
}
}
12 changes: 12 additions & 0 deletions docs/saving/sample/EFSaving/Basics/Post.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace EFSaving.Basics
{
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }

public int BlogId { get; set; }
public Blog Blog { get; set; }
}
}
63 changes: 63 additions & 0 deletions docs/saving/sample/EFSaving/Basics/Sample.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace EFSaving.Basics
{
public class Sample
{
public static void Run()
{
using (var db = new BloggingContext())
{
db.Database.EnsureDeleted();
db.Database.EnsureCreated();
}

using (var db = new BloggingContext())
{
var blog = new Blog { Url = "http://sample.com" };
db.Blogs.Add(blog);
db.SaveChanges();

Console.WriteLine($"{blog.BlogId}: {blog.Url}");
}

using (var db = new BloggingContext())
{
var blog = db.Blogs.First();
blog.Url = "http://sample.com/blog";
db.SaveChanges();
}

using (var db = new BloggingContext())
{
var blog = db.Blogs.First();
db.Blogs.Remove(blog);
db.SaveChanges();
}

// Insert some seed data for the final example
using (var db = new BloggingContext())
{
db.Blogs.Add(new Blog { Url = "http://sample.com/blog" });
db.Blogs.Add(new Blog { Url = "http://sample.com/another_blog" });
db.SaveChanges();
}

using (var db = new BloggingContext())
{
db.Blogs.Add(new Blog { Url = "http://sample.com/blog_one" });
db.Blogs.Add(new Blog { Url = "http://sample.com/blog_two" });

var firstBlog = db.Blogs.First();
firstBlog.Url = "";

var lastBlog = db.Blogs.First();
db.Blogs.Remove(lastBlog);

db.SaveChanges();
}
}
}
}
12 changes: 12 additions & 0 deletions docs/saving/sample/EFSaving/CascadeDelete/Blog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Collections.Generic;

namespace EFSaving.CascadeDelete
{
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }

public List<Post> Posts { get; set; }
}
}

0 comments on commit 6bb7689

Please sign in to comment.