Форум программистов, компьютерный форум, киберфорум
Наши страницы
C#: ASP.NET MVC
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
dailydose
661 / 207 / 88
Регистрация: 21.07.2016
Сообщений: 1,036
Записей в блоге: 2
Завершенные тесты: 1
1

Entity Framework - Частичное обновление строки в таблице

03.03.2018, 10:34. Просмотров 859. Ответов 8
Метки нет (Все метки)

Доброго дня.

Есть простая таблица в базе
SQL
1
2
3
4
5
6
7
CREATE TABLE [dbo].[Users]
(
    [Id] INT NOT NULL PRIMARY KEY, 
    [FirstName] VARCHAR(50) NOT NULL, 
    [LastName] VARCHAR(50) NOT NULL, 
    [Age] INT NOT NULL
)
Как правильно написать метод контроллера для обновление одной(или более колонок) ?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
        [HttpPatch]
        public ActionResult Patch([FromBody]User userData)
        {
            var user = Db.Users.FirstOrDefault(entity => entity.Id== userData.Id);
            if (userTokenData == null)
            {
                return null;
            }
 
            user.FirstName = userData.FirstName; // ??
            Db.SaveChanges();
            return Json(user);
        }
Чтобы можно было отсылать запросы вида:
Javascript
1
{ Id: 1, Age: 42 }
Обновиться должна только колонка Age

Javascript
1
{ Id: 1, FirstName: "Alex", LastName: "Ander" }
Обновиться должны колонки FirstName и LastName
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.03.2018, 10:34
Ответы с готовыми решениями:

Entity Framework один ко многим в одной таблице
Добрый день. столкнулся с проблемой. Использую CodeFirst. Нужно сделать связь 1 ко многим к одной и...

Частичное обновление модели
Добрый вечер. Есть модель представления: public class AdminProductModel { ...

Частичное обновление веб страницы
Работаю с бд в которой несколько тысяч строк данных. Для снижения нагрузки хочу организовать такую...

Добавление в Entity Framework
Гуглил, но не особо понял , что нужно , чтобы пофиксить это Выборка нормально, а если добавлять и...

MVC + Entity Framework
Подскажите плз ORM, а возможно и СУБД для более комфортной работы. Планируется написание проекта...

8
_exp10der_
Warrior
492 / 419 / 177
Регистрация: 23.11.2014
Сообщений: 932
03.03.2018, 13:54 2
Лучший ответ Сообщение было отмечено dailydose как решение

Решение

dailydose, Использовать ChangeTracking API

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
using System;
using System.Reflection;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;
 
namespace ConsoleApp697
{
    internal class Program
    {
        public const string ConnectionString = @"Server=ms.sql;Database=ApplicationDb;User=sa;Password=Pass@word;";
 
        public static readonly LoggerFactory LoggerFactory
            = new LoggerFactory(new[] {new ConsoleLoggerProvider((_, __) => true, true)});
 
        private static void Main(string[] args)
        {
            var migrationsAssembly = typeof(Program).GetTypeInfo().Assembly.GetName().Name;
 
            var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
            builder.UseLoggerFactory(LoggerFactory);
            builder.UseSqlServer(ConnectionString, sql => sql.MigrationsAssembly(migrationsAssembly));
 
            using (var db = new ApplicationDbContext(builder.Options))
            {
                db.Database.Migrate();
                db.Doctors.Add(new Doctor {Age = 25, Name = "Alex"});
                db.SaveChanges();
            }
 
            using (var db = new ApplicationDbContext(builder.Options))
            {
                var updateDoctor = new Doctor {Id = 1, Name = "New"};
                db.Doctors.Attach(updateDoctor);
                db.Entry(updateDoctor).Property(i => i.Name).IsModified = true;
                db.SaveChanges();
            }
 
            using (var db = new ApplicationDbContext(builder.Options))
            {
                var doctor = db.Doctors.Find(1);
                Console.WriteLine(doctor);
            }
        }
    }
 
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        { }
 
        public DbSet<Doctor> Doctors { get; set; }
 
        protected override void OnModelCreating(ModelBuilder modelBuilder) => modelBuilder.ApplyConfiguration(new DoctorConfiguration());
    }
 
    public class Doctor
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
 
        public override string ToString() => $"{nameof(Id)}: {Id}, {nameof(Name)}: {Name}, {nameof(Age)}: {Age}";
    }
 
    internal class DoctorConfiguration : IEntityTypeConfiguration<Doctor>
    {
        public void Configure(EntityTypeBuilder<Doctor> builder)
        {
            builder.HasKey(i => i.Id);
 
            builder.Property(i => i.Name).IsRequired();
 
 
            builder.ToTable("Doctors");
        }
    }
 
 
    internal class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext>
    {
        public ApplicationDbContext CreateDbContext(string[] args)
        {
            var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
            builder.UseSqlServer(Program.ConnectionString);
            return new ApplicationDbContext(builder.Options);
        }
    }
}
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FROM microsoft/dotnet:2.0-runtime AS base
WORKDIR /app
 
FROM microsoft/dotnet:2.0-sdk AS build
WORKDIR /src
COPY ConsoleApp697.sln ./
COPY ConsoleApp697/ConsoleApp697.csproj ConsoleApp697/
RUN dotnet restore -nowarn:msb3202,nu1503
COPY . .
WORKDIR /src/ConsoleApp697
RUN dotnet build -c Release -o /app
 
FROM build AS publish
RUN dotnet publish -c Release -o /app
 
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "ConsoleApp697.dll"]
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
version: '3'
 
services:
  consoleapp697:
    image: consoleapp697
    build:
      context: .
      dockerfile: ConsoleApp697/Dockerfile
    depends_on:
      - ms.sql
  ms.sql:
    image: microsoft/mssql-server-linux
    environment:
      - MSSQL_SA_PASSWORD=Pass@word
      - ACCEPT_EULA=Y
    ports:
      - "5433:1433"
1
Миниатюры
Entity Framework - Частичное обновление строки в таблице  
Вложения
Тип файла: zip ConsoleApp697.zip (112.1 Кб, 3 просмотров)
dailydose
661 / 207 / 88
Регистрация: 21.07.2016
Сообщений: 1,036
Записей в блоге: 2
Завершенные тесты: 1
03.03.2018, 14:08  [ТС] 3
_exp10der_, огромное спасибо! В который раз выручаете

Добавлено через 7 минут
_exp10der_, только здесь 1 нюанс:
C#
1
2
3
4
5
6
7
8
9
            using (var db = new ApplicationDbContext(builder.Options))
            {
                var updateDoctor = new Doctor {Id = 1, Name = "New"};
                db.Doctors.Attach(updateDoctor);
 
                // обновляем имя у доктора
                db.Entry(updateDoctor).Property(i => i.Name).IsModified = true;
                db.SaveChanges();
            }
Вы заранее знаете какое свойство нужно обновить, в данном случае Name.

Добавлено через 2 минуты
Или будет более правильным вариантом создавать новые методы контроллера под каждое поле?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
        [HttpPatch("FirstName")]
        public ActionResult PatchFirstName([FromBody]User userData)
        {
            var user = Db.Users.FirstOrDefault(entity => entity.Id== userData.Id);
            if (userTokenData == null)
            {
                return null;
            }
 
            user.FirstName = userData.FirstName;
            Db.SaveChanges();
            return Json(user);
        }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
        [HttpPatch("Age")]
        public ActionResult PatchAge([FromBody]User userData)
        {
            var user = Db.Users.FirstOrDefault(entity => entity.Id== userData.Id);
            if (userTokenData == null)
            {
                return null;
            }
 
            user.Age = userData.Age;
            Db.SaveChanges();
            return Json(user);
        }
0
_exp10der_
Warrior
492 / 419 / 177
Регистрация: 23.11.2014
Сообщений: 932
03.03.2018, 14:08 4
dailydose, Ну если вы не скажите ChangeTracking API EF какое поле нужно обновлять как он поймет тогда? Разве что телепатически
0
03.03.2018, 14:08
dailydose
661 / 207 / 88
Регистрация: 21.07.2016
Сообщений: 1,036
Записей в блоге: 2
Завершенные тесты: 1
03.03.2018, 14:15  [ТС] 5
_exp10der_, имеется ввиду
Javascript
1
2
3
4
5
6
7
8
9
10
11
var payload = { Id: 1, Age: 42 };
  fetch('http://localhost:5000/api/user', {
      method: 'PATCH',
      body: JSON.stringify(payload),
      headers: {
          'Accept': 'application/json, text/plain, */*',
          'Content-Type': 'application/json'
      }
  })
      .then((response) => response.text())
      .then((data) => console.log(data));
и соотв
Javascript
1
2
3
4
5
6
7
8
9
10
11
var payload = { Id: 1, FirstName: "Alex", LastName: "Ander" };
  fetch('http://localhost:5000/api/user', {
      method: 'PATCH',
      body: JSON.stringify(payload),
      headers: {
          'Accept': 'application/json, text/plain, */*',
          'Content-Type': 'application/json'
      }
  })
      .then((response) => response.text())
      .then((data) => console.log(data));
0
_exp10der_
Warrior
492 / 419 / 177
Регистрация: 23.11.2014
Сообщений: 932
03.03.2018, 14:18 6
dailydose, Да я не понял что именно надо если вы пишите CRUD то update обычно делают по всем филдам если у вас реляционная база данных. Например если бы у вас был no sql обычно в виде json можно сделать мерж в таком случ.

Вот пример есть с CRUD если нужен механизм делают через HTTP PUT

https://github.com/dotnet-presentati...troller.cs#L89

https://github.com/dotnet-presentati...%20Refactor.md
1
dailydose
661 / 207 / 88
Регистрация: 21.07.2016
Сообщений: 1,036
Записей в блоге: 2
Завершенные тесты: 1
03.03.2018, 14:20  [ТС] 7
допустим в том же PHP(Laravel/Eloquent) это реализуется примерно так:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
     * Метод обновления события
     *
     * @param $request
     * @param $id
     * @return \Illuminate\Http\JsonResponse
     */
    public function update($request, $id)
    {
        if(!JsonSchemaValidator::validate('update.schema.json')) {
            return API::getResponse();
        }
        $requestData = $request->json()->all();
        $attributes = API::deserializeModel($requestData);
        $relationships = API::deserializeModelAndExtractIncluded($requestData);
        $validator = Validator::make(array_merge(['id' => $id], $attributes), [
            'id' => 'exists:scheduled_events,id|i_has_access_of_event',
            'event_type' => 'required|in:meeting,conference,task,webinar',
            'start_from' => 'required|date_format:Y-m-d H:i:s',
            'end_to' => 'required|date_format:Y-m-d H:i:s',
            'description' => 'required',
            'transports' => 'required|intersect:websocket,mail',
            'notify_everyone' => 'required|boolean',
            'confirmation_required' => 'required|boolean'
        ], [
            'id.exists' => 'События с данным ID не существует',
            'id.i_has_access_of_event' => 'Вы не имеете доступа к данному событию',
            'event_type.required' => 'Тип события не указан',
            'event_type.in' => 'Создание события с таким типом невозможно',
            'start_from.required' => 'Не указана дата начала события',
            'start_from.date_format' => 'Дата начала события не соответствует формату',
            'end_to.required' => 'Не указана дата окончания события',
            'end_to.date_format' => 'Дата окончания события не соответствует формату',
            'description.required' => 'Не указано описание события',
            'transports.required' => 'Не указаны способы доставки уведомления',
            'transports.intersect' => 'Одно или более наименований транспортов не входит в допустимый список',
            'notify_everyone.required' => 'Не указан флаг отправки уведомлений участникам',
            'notify_everyone.boolean' => 'Флаг отправки не соответствует булеву типу данных',
            'confirmation_required.required' => 'Не указан флаг запроса участия',
            'confirmation_required.boolean' => 'Флаг запроса участия не соответствует булеву типу данных'
        ]);
        if(!$validator->passes()) {
            API::addValidationErrors($validator);
            return API::getResponse();
        }
        $event = ScheduledEvent::updateWithRelated($id, $attributes, $relationships);
        $eventWithRelation = ScheduledEvent::with('scheduled_event_member')
            ->with('scheduled_event_address')
            ->where('id', $event->id)
            ->first();
        event(new ScheduledEventEditEvent($event));
        API::serializeModel($eventWithRelation);
        return API::getResponse();
    }
+ Здесь есть еще и валидация

Добавлено через 2 минуты
Цитата Сообщение от _exp10der_ Посмотреть сообщение
Да я не понял что именно надо если вы пишите CRUD то update обычно делают по всем филдам если у вас реляционная база данных.
т.е. с фронтенда получается нужно будет отправлять полностью всю модель? Включая как и обновленные, так и не обновленные поля?
0
_exp10der_
Warrior
492 / 419 / 177
Регистрация: 23.11.2014
Сообщений: 932
03.03.2018, 14:25 8
dailydose, ну тогда придется самому писать хелпер.
Например на бэке принимать Dictionary<string, object> проходить по филдам(обычный foreach) искать в ваше представлении объекта записи таблицы(User) такие проперти и помечать через ChangeTracking API что филд надо обновить.

Добавлено через 1 минуту
Цитата Сообщение от dailydose Посмотреть сообщение
т.е. с фронтенда получается нужно будет отправлять полностью всю модель? Включая как и обновленные, так и не обновленные поля?
Да обычно так и поступают если у вас реляционная база данных. В NoSQL можно было бы просто документ смержить json'ном.
1
dailydose
661 / 207 / 88
Регистрация: 21.07.2016
Сообщений: 1,036
Записей в блоге: 2
Завершенные тесты: 1
03.03.2018, 16:26  [ТС] 9
Цитата Сообщение от _exp10der_ Посмотреть сообщение
Да обычно так и поступают если у вас реляционная база данных
Фишка в том, что by desgin интерфейс ориентирован на точечное обновление модели, у которой полей 10 штук и как-то не очень хотелось бы по сети гонять лишние данные)

Цитата Сообщение от _exp10der_ Посмотреть сообщение
на бэке принимать Dictionary<string, object> проходить по филдам(обычный foreach) искать в ваше представлении объекта записи таблицы(User) такие проперти и помечать через ChangeTracking API что филд надо обновить.
Хорошая идея, попробую поступить именно так.
0
03.03.2018, 16:26
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.03.2018, 16:26

Связь 1-1 entity framework
Преподаватель предоставил вот такую схему: Я создал классы таблиц, но вот как их связать один к...

Проблемка с Entity Framework
Здравствуйте, проблема такого плана - пока файл с .edmx расширением создается в рамках веб-сайта...

Entity FrameWork for VS 2015
У меня есть библиотека классов. И их функционал нужно перенести в таблицы в microsoft sql. Я слышал...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru