Skip to content

Instantly share code, notes, and snippets.

@zxdcm
Last active January 2, 2020 15:01
Show Gist options
  • Save zxdcm/928ddcd80da9179009e0744a76179476 to your computer and use it in GitHub Desktop.
Save zxdcm/928ddcd80da9179009e0744a76179476 to your computer and use it in GitHub Desktop.
Entity Framework
https://www.learnentityframeworkcore.com/
1. Adding
2. Modifying
a)
var author = context.Authors.First(a => a.AuthorId == 1);
author.FirstName = "Bill";
context.SaveChanges();
Generates sql that updates only FirstName prop of author entity
b)
public void Save(Author author)
{
context.Entry(author).State = EntityState.Modified;
context.SaveChanges();
}
Any related objects will not be tracked (props of Author, like List<Book> books)
Generate SQL that updates all properties (except primary key)
c)
context.Update()
context.SaveChanges()
Update all properties. Related objects will be updated too. For related objects without
Primary key will be generated INSERT statement
d) Attach
When atatch, state will be set to Unchanged. (no sql code generated at all)
Reachable entities without key values => marked as Added
However, now the entityis being tracked by context, so can inform which properties were
modified (and proper sql will be generated):
context.Attach(author);
context.Entry(author).Property("FirstName").IsModified = true;
e) TrackGraph
Complex object.
For example:
it is assumed that the author entity has not been changed,
but the books might have been edited
// author is not tracked by EF yet
context.ChangeTracker.TrackGraph(author, e => {
if((e.Entry.Entity as Author) != null)
e.Entry.State = EntityState.Unchanged //EF now tracks the author entity
else
e.Entry.State = EntityState.Modified; //If author property is Books
});
=> update all the books field by field
3. Deleting
a) c
context.Remove(context.Authors.Single(a => a.AuthorId == 1));
context.SaveChanges();
Produces 2 SQL queries : select & delete
b)
context.Remove(new Author { AuthorId = 1 };);
context.SaveChanges();
Creates stub and delete. Execute only 1 request.
c) context.Entry(author).State = EntityState.Deleted;
Related Data:
If the entity that you want to delete has related data,
the approach that you take will depend on how the relationship has been configured.
(if configured in sql or by fluent api)
4. Change Tracker
Added
Unchanged
Modified
Deleted
DbSets:
QueryingData
Find - shorthand (syntactic sugar) for the SingleOrDefault method
^ May return null.
Single, FirstOrDefault - execute's immediately
GroupBy - in EF 2.1 executes in-memory.
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
^ instead of .AsNotTracking() in each read-request
AddingData
[ConcurrencyCheck]
При обновлении, добавит в where предикат, со значением поля на момент извлечения.
Т.е
class Model {
[ConcurrencyCheck]
public string BloggerName { get; set; }
}
where (([PrimaryTrackingKey] = @4) and ([BloggerName] = @5))
@4=1,@5=N'Julie' ^ !!!!!!!!!!!!
Если значение изменится, то DbUpdateConcurrencyException
[TimeStamp]
Тоже для concurrency checking.
byte[], не nullable
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
InverseProperty
^ Если два объекта одного типа в классе, то EF не может сам разобраться
The InverseProperty is used when you have multiple relationships between classes.
EF кэширует результат операции Find.
var blog = context.Blogs.Find(3);
// Will return the same instance without hitting the database
var blogAgain = context.Blogs.Find(3);
С IQueryable такое не работает, запрос все равно будет, но EF вернет, вероятно, те же объекты что и после первого запроса.
Find - возвращает объект из контекста, без дополнительного запроса. Добавленные объекты, но не сохраненные в базе возвращаются
Query - делает запрос к базе, присоединяет объекты к контексту (если появились новые), возвращает объекты из контекста (Если уже были!). Добавленные объекты, но не сохраненные в базе не возвращаются
Insert or update pattern
context.Entry(blog).State = blog.BlogId == 0 ?
EntityState.Added :
EntityState.Modified;
context.SaveChanges();
Handling Concurrency Conflicts
Resolving optimistic concurrency exceptions with Reload (database wins)
using (var context = new BloggingContext())
{
var blog = context.Blogs.Find(1);
blog.Name = "The New ADO.NET Blog";
bool saveFailed;
do
{
saveFailed = false;
try
{
context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
saveFailed = true;
// Update the values of the entity that failed to save from the store
ex.Entries.Single().Reload();
}
} while (saveFailed);
}
Resolving optimistic concurrency exceptions as client wins
using (var context = new BloggingContext())
{
var blog = context.Blogs.Find(1);
blog.Name = "The New ADO.NET Blog";
bool saveFailed;
do
{
saveFailed = false;
try
{
context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
saveFailed = true;
// Update original values from the database
var entry = ex.Entries.Single();
entry.OriginalValues.SetValues(entry.GetDatabaseValues());
}
} while (saveFailed);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment