Dziwna sprawa - aplikacja nie czyta zaktualizowanej bazy

0

Mam mega zagwozdkę. Krótko - w aplikacji webowej edytowane są transakcje i jeżeli zmiana dotyczy kwot albo dat transakcji, wysyłana jest informacja na kolejkę, że trzeba przeliczyć salda. To odczytuje aplikacja konsolowa, która dokonuje na bazie przeliczeń.

Rzecz w tym, że aplikacja bierze pod uwagę tylko pierwszą zmianę w bazie. Jeżeli zmieniam datę transakcji na danym rekordzie, to przy pierwszym komunikacie aplikacja zaczytuję tę datę z bazy, natomiast już jak drugi raz zmienię datę transakcji dla tego samego rekordu, to aplikacja czyta cały czas tę poprzednią wartość. Oczywiście w samej bazie jest poprawnie. Chyba coś jest porąbane z obsługą bazy w tej aplikacji konsolowej. Podaje istotne części kodu. Wiadomości z kolejki się zaczytują poprawnie, problem pojawia się tylko przy odczycie danych z bazy.

public class BavServiceDbContext: DbContext
    {
		public DbSet<Account> Accounts { get; set; }
		public DbSet<Transaction> Transactions { get; set; }

		protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
		{
			optionsBuilder.UseMySql(conn, MySqlServerVersion.LatestSupportedServerVersion);
		}
	}

class Program
	{
		static readonly BavServiceDbContext _ctx = new BavServiceDbContext();

		static void Main(string[] args)
		using (var bus = RabbitHutch.CreateBus(conn_rabbit))
			{
				Console.WriteLine("Connected to RabbitMQ.");
				SubClient(bus);
			}
		}

        private static void SubClient(IBus bus)
		{
			using (var sub = bus.PubSub.Subscribe<RecalcBalanceReq>("bav", msg => PubMessageReceived(msg)))
			{ 
				while (true)
				{
					Thread.Sleep(100);
				}
			}
		}

        private static void PubMessageReceived(RecalcBalanceReq msg)
		{
            var tran = _ctx.Transactions.Where(x => x.IdTransaction == msg.IdTransaction).FirstOrDefault();
            Console.WriteLine("New TransactionDate: {0}", tran.TransactionDate);
        }
2

Na oko problem z transakcjami, być może event jest wysyłany przed zrobieniem COMMIT? (Jeden statement ma implicit transaction, czyli może być specjalnie obsłużony).
Pokaż kod co zapisuje, bo ten co odczytuje wygląda OK.

Generalnie wysyłaj event, po tym jak zrobiłeś commit na transakcji bazodanowej.

0

@0xmarcin: to nie to. Kod po stronie API wygląda tak:

   _context.Update(existing);
                    Log.Information("Transaction modified");
                }
                _context.SaveChanges();

                if (req.IdTransaction == 0)
                     req.IdTransaction = new_tran.IdTransaction;
               _bus.PubSub.Publish(req);
            }

co więcej, w logach bazy po każdym updacie widzę commita...

1

Nie wiem jak masz zaimplementowane DbContext czy wstrzykujesz czy co tam się dzieje. ale EF ma to do siebie jeśli twój DbContext utworzysz tylko raz (singleton) to to co odczyta z bazy zostanie "zcachowane" w ef, Jeśli inna aplikacja lub ręcznie zmienisz dane w bazie to ef i tak tej zmiany nie zauważy bo trzyma stan z poprzedniego odczytu. Jeśli dokonasz zmian na tym samym obiekcie DbContext to nie ma problemu bo to zarejestruje. Najlepiej przy odczycie lub zapisie tworzyć nowa instancje obiektu DbContext poprzez using. np. using BavServiceDbContext = new();

0

mam w namespace Program uruchomiony kontekst:

static readonly BavServiceDbContext _ctx = new BavServiceDbContext();

korzystam z niego w całej aplikacji od strony konsoli globalnie.

0

to spróbuj zrobić tak jak napisałem. jesli to asp.net i uzywasz api to jak wstrzykniesz sobie przez DI DbContext to jest on rejestrowany jako scpoe. czyli przy każdym strzale do api jest tworzony na nowo

0

@kal800: a jawnie transakcji nigdzie nie rozpoczynasz?
Bo widzę, że w samplu pokazałeś SaveChanges i po nim publish wiadomości. Jeśli dopiero później by poszedł commit transakcji to w zależności od stopnia izolacji, handler eventu mógłby odczytać poprzednią wartość z bazy.

0

@some_ONE: Wszystko wygląda prawilnie:

2021-10-22T20:38:30.264190Z	  516 Query	set session transaction isolation level repeatable read
2021-10-22T20:38:30.269735Z	  516 Query	start transaction
2021-10-22T20:38:30.274088Z	  516 Query	UPDATE `Transactions` SET (...)
2021-10-22T20:38:30.274403Z	  516 Query	SELECT ROW_COUNT()
2021-10-22T20:38:30.278064Z	  516 Query	commit
1

@sosnek: zrobiłem wszędzie using () i zaczęło działać - dane aktualne się pobierają. Dzięki.

Ech, ten EF nie przestaje zaskakiwać...

0

Wystarczy czytac dokumentacje.
Masz jak byk napisane przynajmniej w kilku miejscach, ze DbContext nie jest thread safe.

To tak jakbys mial jakas liste singletona, do ktorej jednoczesnie zapisuje i odczytuje z niej multum klientow i mial pretensje, ze lista jest dziwna.

1 użytkowników online, w tym zalogowanych: 0, gości: 1