实体框架核心轨道图用于断开连接的数据

实体框架核心是新的轻量级版本的实体框架,旨在使用.NET核心应用程序。就像ASP.NET核心一样,它已从地上重写,并包括一些新的做事方式。其中一个是引入用于处理断开的场景中的复杂数据的曲目映图方法,例如MVC或Web API应用程序。

实体框架能够基于其对任何给定实体图的当前状态的理解来生成要执行的正确SQL。它知道这一点,因为它的ChangeTracker组件会跟踪实体会发生什么。这在这种情况下,这实际上很好:

using (var context = new TestContext())
{
    var author = context.Authors.Single(a => a.AuthorId == 1);
    author.FirstName = "Bill";
    context.SaveChanges();
}

The author entity is retrieved via the context which starts tracking it immediately. When the SaveChanges method is called, EF will detect any changes made to the entity it is tracking and generate SQL accordingly. In this example, only the FirstName property was changed:

exec sp_executesql N'SET NOCOUNT ON;
UPDATE[Authors] SET[FirstName] = @p0
WHERE[AuthorId] = @p1;
SELECT @@ROWCOUNT;
',N'@p1 int,@p0 nvarchar(4000)',@p1=1,@p0=N'Bill'

当您希望使用从上下文的当前实例中没有出现的实体时,情况变得更加复杂。它们可能由于发布到MVC动作方法而来,然后由模型粘合剂从形式值构成。他们可以在Web API方法中从JSON次数抵达。如果希望上下文来处理任何更改,则需要将实体引入上下文,并且需要通知上下文了解所需的操作。

实体框架 Core retains the DbContext Add and Attach methods from previous versions. It also includes a new Update method, and these methods work well for individual entities or in cases where you don't mind all properties being included in an UPDATE statement whether they were changed or not. Entity Framework Core also introduces a new method called TrackGraph, which enables you to navigate the entire object graph of a given entity (i.e. the root entity and all related entities, and all entities related to the related entities and so on, recursively), and to specify the action that should take place accordingly.

这是一个对象图(对于示例的目的而言):

var author = new Author
{
    AuthorId = 1,
    FirstName = "William",
    LastName = "Shakespeare"
};
author.Books.Add(new Book { AuthorId = 1, BookId = 1, Title = "Hamlet", Isbn = "1234" });
author.Books.Add(new Book { AuthorId = 1, BookId = 2, Title = "Othello", Isbn = "4321" });
author.Books.Add(new Book { AuthorId = 1, BookId = 3, Title = "MacBeth", Isbn = "5678" });

Let's assume that the only thing that was changed was the ISBN numbers assigned to each book and that this object graph is presented to aSavemethod somewhere in a repository or service layer. The Save method makes use of the new DbContext.Update method:

public void Save(Author author)
{
    using(var context = new TestContext())
    {
        context.Update(author);
        context.SaveChanges();
    }
}

This works. The Update method will result in the root entity and all related entities being tracked as Modified, and SQL will be generated to update all of their properties to the values that have been assigned to the entities, whether they have been changed or not. That means that all of the values for all of the entities have to be present, otherwise they will be overwritten with null or default values.

The TrackGraph method offers finer-grained control since it provides easy access to each entity in the graph. Here's how the Save method might look instead:

public void Save(Author author)
{
    using (var context = new TestContext())
    {
        context.ChangeTracker.TrackGraph(author, e =>
            {
                e.Entry.State = EntityState.Unchanged;
                if ((e.Entry.Entity as Book) != null)
                {
                    context.Entry(e.Entry.Entity as Book).Property("Isbn").IsModified = true;
                }
            });
        context.SaveChanges();
    }
}

The TrackGraph method takes two arguments: the root entity to start tracking from, and a callback delegate to be performed on each entity that is discovered by recursion. In this example, the callback starts by applying an EntityState value to each entity so that it can be tracked. This is important for descendant discovery. If an entity is not assigned an EntityState value, it will not be tracked and its descendants will not be discovered. The UnChanged state is applied which will result in no action being taken by the context. However, if an entity is a Book type, its Isbn property is marked as modified, which results in the EntityState for that entity being changed to Modified. And then, just like in the example at the beginning of the article, SQL is generated that only updates the Isbn property:

exec sp_executesql N'SET NOCOUNT ON;
UPDATE[Books] SET[Isbn] = @p0
WHERE[BookId] = @p1;
SELECT @@ROWCOUNT;
UPDATE[Books] SET[Isbn] = @p2
WHERE[BookId] = @p3;
SELECT @@ROWCOUNT;
UPDATE[Books] SET[Isbn] = @p4
WHERE[BookId] = @p5;
SELECT @@ROWCOUNT;
',N'@p1 int,@p0 nvarchar(4000),@p3 int,@p2 nvarchar(4000),@p5 int,@p4 nvarchar(4000)',
@p1=1,@p0=N'1234',
@p3=2,@p2=N'4321',
@p5=3,@p4=N'5678'

由于可以指示修改了哪个属性,因此无需对其他属性的值张贴(除了键值之外)。

The body of the delegate that was passed in to the TrackGraph method could easily be factored out as a separate method to aid code re-usability:

void UpdateIsbn(EntityEntryGraphNode node, TestContext context)
{
    node.Entry.State = EntityState.Unchanged;
    if ((node.Entry.Entity as Book) != null)
    {
        context.Entry(node.Entry.Entity as Book).Property("Isbn").IsModified = true;
    }
}

然后可以像这样调用:

public void Save(Author author)
{
    using (var context = new TestContext())
    {
        context.ChangeTracker.TrackGraph(author, e => UpdateIsbn(e, context));
        context.SaveChanges();
    }
}

概括

The TrackGraph method is new in Entity Framework Core, and offers a simple way to iterate over a graph of objects that you want the context to begin tracking, and to apply customised code based on the type of entity and other criteria.

查看有关实体框架核心的更多信息 学习实体框架核心.