Ці павінен я праверыць, калі нешта існуе ў БД і ня хутка або чакаць дб выключэння

Наяўнасць двух класаў:

public class Parent 
{
    public int Id { get; set; }
    public int ChildId { get; set; }
}

public class Child { ... }

Пры прызначэнні ChildId у Parent я павінен праверыць першы, калі ён існуе ў БД або чакаць DB кінуць выключэнне?

Напрыклад (з дапамогай Entity Framework Ядро):

NOTE these kinds of checks are ALL OVER THE INTERNET even on official Microsoft's docs: https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application#modify-the-department-controller but there is additional exception handling for SaveChanges

Акрамя таго, звярніце ўвагу, што галоўная мэта гэтай праверкі павінен быў вярнуцца сяброўская паведамленне і вядомае стан HTTP да карыстача API і не цалкам ігнараваць выключэння базы дадзеных. І адзінае месца, пры ўзнікненні выключэння ўнутры SaveChanges або SaveChangesAsync выклік ... так што не будзе ніякіх выключэнняў пры выкліку FindAsync або Любы . Так што, калі дзіця існуе, але быў выдалены перад SaveChangesAsync , то паралелізм будзе згенеравана выключэнне.

Я зрабіў гэта з-за таго, што вонкавага ключа парушэнне выключэнне будзе нашмат складаней фармат для адлюстравання «Дзіця з ідэнтыфікатарам {parent.ChildId} не можа быць знойдзены.»

public async Task> CreateParent(Parent parent)
{
   //is this code redundant?
  //NOTE: its probably better to use Any isntead of FindAsync because FindAsync selects *, and Any selects 1
    var child = await _db.Children.FindAsync(parent.ChildId);
    if (child == null)
       return NotFound($"Child with id {parent.ChildId} could not be found.");

    _db.Parents.Add(parent);    
    await _db.SaveChangesAsync();        

    return parent;
}

супраць:

public async Task> CreateParent(Parent parent)
{
    _db.Parents.Add(parent);
    await _db.SaveChangesAsync(); //handle exception somewhere globally when child with the specified id doesn't exist...  

    return parent;
}

The second example in Postgres will throw 23503 foreign_key_violation error: https://www.postgresql.org/docs/9.4/static/errcodes-appendix.html

Недахоп апрацоўкі выключэнняў такім чынам, у ОРМЕ, як EF з'яўляецца тое, што ён будзе працаваць толькі з пэўнай базай дадзеных уліковых запісаў. Калі вы калі-небудзь хацелі, каб пераключыцца на SQL-сервер ці нешта яшчэ гэта больш не будзе працаваць, таму што код памылкі зменіцца.

Ня фарматаванне выключэння належным чынам для канчатковага карыстальніка можа раскрыць некаторыя рэчы, якія вы не хочаце, каб хто-небудзь, але распрацоўшчыкі бачыць.

звязаны:

https://stackoverflow.com/ пытанні/6171588/прадухіленне гонкі ўмова з-калі-існуе для абнаўлення-ELSE-устаўка-в-сутнасць-рамкі

https://stackoverflow.com/questions/ 4189954/рэалізацыі, калі-ня-існуе-устаўка-выкарыстоўваючы-сутнасць-рамкі-без гоначных умоў

https://stackoverflow.com/questions/308905/should-there- быць-а-транзакцыю-для-чытання, запытаў

26
Калі дадатковы запыт, каб забяспечыць паведамленне чытэльных памылак, не вынікае, што адбудзецца пасля таго, як мы ведаем, што ёсць памылка, а не раней? гэта значыць <�Код> lock_db {спроба {дадаць ()} злавіць (db_error) {калі (id_not_present ()) {вярнуцца NotFound (); } Яшчэ {вярнуць OtherError (); }} . Я не спецыяліст дастаткова, каб ператварыць гэта ў рэальны код, але гэта тое, што я чакаў.
дададзена аўтар Kenneth Kryger Sørensen, крыніца
@Konrad. Я падазраю, што ў рэшце рэшт, гэта цалкам залежыць ад яго выкарыстання. Калі гэты ідэнтыфікатар з'яўляецца правільным 99% час, вы, верагодна, знайсці яго хутчэй, каб не праверыць (таму што праверка заўсёды дадатковая праца), і рабіць якую-небудзь радок памылкі фарматавання ў кодзе апрацоўкі памылак (які ў дадзеным выпадку ўключае ў сябе апрацоўку выключэнняў - вы можаце паўторна выдаць, калі гэта не канкрэтная памылка, якую вы чакалі). Калі ідэнтыфікатар няправільна 99% часу, гэта будзе хутчэй зрабіць чэк. Вымераць яго ўбачыць.
дададзена аўтар Kenneth Kryger Sørensen, крыніца
Праверка на самай справе робіць дзве рэчы: 1) ўваход праверкі, 2) прадстаўленне пра памылку. Вы можаце аб'яднаць гэтыя два ў адзін, калі вы падтрымліваеце стан базы дадзеных (блакіроўкі/транзакцыю), ці то і іншае паасобку.
дададзена аўтар Kenneth Kryger Sørensen, крыніца
І я думаю, што гэта апраўдвае неабходнасць дадатковага кода <> SELECT запыт
дададзена аўтар Scott Young, крыніца
@ Базы дадзеных user673679 дае памылку як «парушэнне знешняга ключа», цяпер спрабуюць і фармат, што «Дзіця з ідэнтыфікатарам {parent.ChildId} не можа быць знойдзены.» таму што вы не хочаце, каб ваш канчатковы карыстальнік нічога ведаць аб вашай асноўнай базе дадзеных. Проста вяртанне 500 Унутраная памылка сервера або 404 Not Found не гаворыць вам што-небудзь з пункту гледжання карыстальніка, так што вы павінны ведаць, што менавіта пайшло не так, каб вы маглі выправіць гэта і паспрабуйце ізноў.
дададзена аўтар Scott Young, крыніца
Выключэння прызначаныя для распрацоўшчыкаў, а не для канчатковых карыстальнікаў, так што вам прыйдзецца фарматаваць не вельмі значную памылку з за выключэннем базы дадзеных у зручным для карыстальніка паведамленні.
дададзена аўтар Scott Young, крыніца
Акрамя таго, у маім 1-ым прыкладзе кода я хацеў бы выкарыстаць Любы замест Знайсці , калі мне не трэба чытаць што-небудзь ад дзіцяці, таму што ORM пераўтворыць яго ў ВЫБРАЦЬ 1 замест SELECT *
дададзена аўтар Scott Young, крыніца
@JaredSmith Я ведаю, што стан гонкі і блакіроўка.
дададзена аўтар Scott Young, крыніца
@JaredSmith але FYI FindAsync ня выкідвае ніякіх выключэнняў падобнага
дададзена аўтар Scott Young, крыніца
калі нешта мяняецца адначасова пасля выкліку FindAsync і дадзеныя супярэчлівыя, то будзе згенеравана выключэнне пры SaveChangesAsync
дададзена аўтар Scott Young, крыніца
Я быў бы больш шчаслівы мець адказ з практычным прыкладам задачы з прыкладамі кода, дзе яна не працуе
дададзена аўтар Scott Young, крыніца
Напрыклад: калі вы карыстаецеся Знайсці , але хто-то дадае запіс з гэтым канкрэтным ідэнтыфікатарам, то нічога страшнага не адбудзецца, гэта будзе проста вярнуць 404 не знойдзена. Але калі хто-то выдаляе яго ў той жа час ці нешта іншае, то гэта ўплывае на астатнюю частку працы.
дададзена аўтар Scott Young, крыніца
@JaredSmith Я думаю, ты блытаеш мяне, я ведаю, што ўмовы гонкі не звязаныя з выключэннямі, але ты путаешь паняцці тут умоў гонкі вы маеце справу з у вашым кодзе супраць умоў гонкі ў базе дадзеных.
дададзена аўтар Scott Young, крыніца
@JaredSmith не рэальна, таму што ўмовы гонкі ў базе дадзеных апрацоўваюцца па-рознаму на мове па вашаму выбару
дададзена аўтар Scott Young, крыніца
напрыклад, у дадзеным выпадку, калі я выкарыстоўваю EF Core, ён будзе кідаць выключэнне, калі ёсць стан гонкі ў базе дадзеных
дададзена аўтар Scott Young, крыніца
@billrichards здаецца разумным :) але што пра выпадак, калі бацькоўскія ўласцівасці залежаць ад уласцівасцяў дзіцяці? Мне трэба запытаць і тады, і код, то не будзе, што адрозніваецца ад майго 1-га прыкладу
дададзена аўтар Scott Young, крыніца
@DanielPryden Выкарыстанне ORM ці не кожны выбар мае некаторыя недахопы, якія вы павінны мець справу з. ИМО гэта не мае значэння, што вы выкарыстоўваеце ў якасці ключа ў гэтым выпадку, паколькі гаворка ідзе пра запыты, так што вы будзеце мець такую ​​ж або падобную праблему, калі не выкарыстоўваецца ORM, і выкарыстоўваць нешта накшталт Dapper ці нейкі мікра-ОРМ.
дададзена аўтар Scott Young, крыніца
і вы ўсё яшчэ можаце непасрэдна выконваць запыты замест таго, каб спадзявацца на аўтаматычнае пакаленне.
дададзена аўтар Scott Young, крыніца
@DanielPryden На маё пытанне, я не казаў, што я не хачу, каб апрацоўваць выключэння базы дадзеных (я ведаю, што выключэння непазбежныя). Я думаю, што многія людзі няправільна зразумелі, я хацеў бы мець сяброўская паведамленне пра памылку для майго Web API (для канчатковых карыстальнікаў чытаць) як Дзіця з ідэнтыфікатарам {parent.ChildId} не можа быць знойдзены. . І фарматаванне «ключ замежнага парушэнні» Я думаю, горш у гэтым выпадку.
дададзена аўтар Scott Young, крыніца
Калі вы спачатку праверыць, калі, напрыклад, запіс ўжо існуе, то ў вас ёсць Oportunity вярнуць карыстацкае паведамленне. Акрамя таго, ён робіць бізнес-правілы больш шматслоўным. Калі я бачу калі (! Exists (пункт)) , я ведаю адразу, што там ніколі не павінны быць дубляваныя запіс.
дададзена аўтар DarrylGodden, крыніца
@Konrad: Калі ў вас ёсць набор палёў, адназначна ідэнтыфікуе запіс, то <�я> павінен ёсць абмежаванне унікальнасці, якое ператварае гэта. Пакуль ваша база дадзеных захавання цэласнасці дадзеных (што павінна быць, што гэта яго праца!), То вам прыйдзецца мець справу з запытамі ад вашага прыкладання, базы дадзеных адпрэчваюць з-за парушэнне абмежаванні. Як Mr.Mindor паказвае ніжэй, гэта сапраўды не-вельмі-спецыяльную асаблівы выпадак апрацоўкі памылак: незалежна ад таго, што вы робіце, гэта не <�я> заўсёды магчыма для ўстаўкі на правал, і вы павінны звяртацца што, незалежна.
дададзена аўтар DWGKNZ, крыніца
@Konrad: Ваша паводзіны па гэтым пытанні дае зразумець, што вы не задавалі гэтае пытанне ў духу добрай волі. Вы хацелі канкрэтны адказ, каб пацвердзіць сваё меркаванне вы ўжо сфармаваныя, перш чым задаць пытанне. Хацець канкрэтны адказ не з'яўляецца няправільным само па сабе, але, як вы займаліся з усімі, хто не згодны з вамі (які, як уяўляецца, на сённяшні дзень большасць) становіцца ясна, што вы больш зацікаўлены ў зацвярджэнні, чым у працэсе навучання. Гэта не вельмі канструктыўнае паводзіны, для грамадства ці для сябе. Вы ніколі не зможаце нічога даведацца, пакуль вы не можаце прызнаць, у вас ёсць чаму павучыцца.
дададзена аўтар DWGKNZ, крыніца
Неяк не звязаны ў баку: многія з праблем, якія апісваюць сімптомы вашага рашэння выкарыстоўваць ОРМ ў першую чаргу. Калі першасны ключ быў натуральны ключ нейкі, ці autoincremented паслядоўнасці, то ў вас не будзе гэтай праблемы наогул. Калі вашы інструменты робяць гэта цяжка для вас, каб пабудаваць добрае рашэнне праблемы, то вам, верагодна, трэба старанна прадумаць, ці трэба вам розныя інструменты.
дададзена аўтар DWGKNZ, крыніца
Сумеснае выкарыстанне даследаванняў дапамагае ўсім . Скажыце нам, што вы ўжо спрабавалі, і чаму ён не адпавядае вашым патрэбам. Гэта сведчыць аб тым, што вы знайшлі час, каб паспрабаваць дапамагчы сабе, гэта ратуе нас ад паўтарыўшы відавочныя адказы, і больш за ўсё гэта дапамагае атрымаць больш канкрэтны і адпаведны адказ. Таксама глядзіце Як папрасіць
дададзена аўтар gnat, крыніца
Гледзячы праз каментары, я павінен сказаць наступнае: <�б> перастаць думаць у банальнасці . «Збой хутка» не з'яўляецца ізаляваным, з кантэксту правілы, якія могуць або павінны быць затым ўсляпую. Гэтае правіла. <�Я> Заўсёды </я> прааналізаваць тое, што вы на самай справе спрабуеце дасягнуць, а затым разгледзець любую тэхніку ў святле ці дапамагае вам дасягнуць гэтай мэты ці не. «Збой хутка» дапамагае прадухіліць ненаўмысных пабочныя эфекты. І да таго ж, "не ў стане хутка» на самай справе азначае, што «не ў стане, як толькі вы можаце выявіць там праблема.» <�Б> І метады непрыдатныя, як толькі выяўляецца праблема, так што вы павінны глядзець на іншыя меркаванні.
дададзена аўтар jmibanez, крыніца
Як ужо згадвалася, існуе верагоднасць таго, што запіс можа быць устаўлены або выдалены адначасова з праверкай на NotFound. Па гэтай прычыне, праверка на першы погляд як непрымальнае рашэнне. Калі вы турбуецеся аб напісанні апрацоўкі выключэнняў Postgres-спецыфічныя, што не падыходзіць для іншых рухавічкоў баз дадзеных, паспрабаваць структураваць апрацоўшчык выключэнняў такім чынам, што базавая функцыянальнасць можа быць пашырана з дапамогай класаў з базамі дадзеных (SQL, Postgres і г.д.)
дададзена аўтар eddyce, крыніца
дададзена аўтар Sujan, крыніца
ня @Konrad ніякай розніцы. Ніхто. Тыя ж праблемы, такое ж рашэнне. Агульныя рэсурсы размяркоўваюцца рэсурсы, ці з'яўляецца яго памяць, файлавая сістэма, база дадзеных і г.д.
дададзена аўтар Sujan, крыніца
Для больш працяглага выкладу см адказ Mr.Mindor: гэта сапраўды добра.
дададзена аўтар Sujan, крыніца
@Konrad, што рабіць выключэньня трэба зь ім рабіць? Спыніце думаць аб гоначных умовах, неяк, што жыве ў вашым кодзе: гэта ўласцівасць Сусвету. Нічога, <�я> што-небудзь </я> што тычыцца рэсурсу, ён не цалкам кіравання (напрыклад, прамы доступ да памяці, сумесна выкарыстоўванай памяці, базы дадзеных, REST API, файлавая сістэма і г.д. і да т.п.) больш чым адзін раз, і чакае, што яна не зменіцца мае патэнцыйнае стан гонкі. Чорт вазьмі, мы маем справу з гэтым у C, які робіць нават не Папрасіць выключэнні. Проста ніколі не разветвляется на стане рэсурсу вы не кантралюеце, калі хаця б адна з галін наблытаў са станам гэтага рэсурсу.
дададзена аўтар Sujan, крыніца
Фраза для першага малюнка, што па нейкай прычыне не адзін згадана не з'яўляецца «стан гонкі». Паглядзіце, што гэта значыць, то заўсёды выкарыстаць другі шаблон назаўжды.
дададзена аўтар Sujan, крыніца

5 адказы

Праверка на унікальнасць, а затым ўстаноўка з'яўляецца антипаттернами; ён заўсёды можа здарыцца так, што ідэнтыфікатар устаўлены паралельна паміж праверкай часу і запісы часу. Базы абсталяваны для вырашэння гэтай праблемы праз такія механізмы, як абмежаванні і здзелкі; большасць моў праграмавання не з'яўляюцца. Таму, калі вы шануеце ўзгодненасць дадзеных, пакіньце яго эксперту (база дадзеных), гэта значыць зрабіць ўстаўку і злавіць выключэнне, калі яно адбываецца.

105
дададзена
праверка і не з'яўляецца не хутчэй, чым проста «спрабуе» і спадзявацца на лепшае. Былы мае на ўвазе 2 аперацыі, якія будуць рэалізаваны і выкананы ў вашай сістэме і 2 у БД, у той час як апошні мае на ўвазе толькі адзін з іх. Праверка дэлегавана да сервера БД. Гэта таксама азначае, адзін менш хмель у сетку і адзін менш задачу ўдзел у БД. Можна было б падумаць, што яшчэ адзін запыт да БД з'яўляецца даступным, але мы часта забываемся думаць ў вялікім. Думайце ў высокай паралельнасці запускаючы запыт зноў і зноў сотні разоў. Гэта можа DUP ўвесь трафік да БД. Калі гэта мае значэнне да вас, каб вырашыць.
дададзена аўтар glacier, крыніца
дададзена аўтар Scott Young, крыніца
Я абнавіў сваё пытанне.
дададзена аўтар Scott Young, крыніца
Але не лепш пацярпець няўдачу хутка?
дададзена аўтар Scott Young, крыніца
Я думаю, што гэта залежыць, таму што, калі некаторыя ўласцівасці Parent будуць залежаць ад уласцівасцяў дзіцяці, то вы павінны прынесці дзіця раней усіх.
дададзена аўтар Scott Young, крыніца
@mtraceur, таму я ў цяперашні час не рабіць і мець асобныя праверкі запытаў.
дададзена аўтар Scott Young, крыніца
калі гэта стане праблемай, то я буду рэарганізаваць і апрацоўваць выключэння БД належным чынам
дададзена аўтар Scott Young, крыніца
@mtraceur, магчыма, вы маеце рацыю, я на самой справе не ўпэўнены, што калі EF Ядро робіць гэта няяўна, як частка здзелкі. Адзіная праблема з гэтым 1 запыт, які не зможа сам па сабе правільна фарматаваннем, каб адправіць яго назад кліенту (дружалюбны карыстачу паведамленне, не падвяргаючы дэталі)
дададзена аўтар Scott Young, крыніца
як я ўжо казаў ёсць сітуацыі (гэта не адзін, хоць), дзе вам трэба 2 запытаў у любым выпадку, калі адна аперацыя залежыць ад слупкоў з розных табліц
дададзена аўтар Scott Young, крыніца
ў вэб-API, вам неабходна супаставіць яго з адпаведным кодам стану 404, як не знайшоў ...
дададзена аўтар Scott Young, крыніца
@ Mr.Mindor так, як вы яе вырашаеце? паставіўшы абедзве праверкі і ўставіць у 1 аб'ём здзелкі?
дададзена аўтар Scott Young, крыніца
як вы можаце бачыць у табліцы SELECT выконваецца адначасова з INSERT UPDATE DELETE
дададзена аўтар Scott Young, крыніца
«Ён заўсёды можа здарыцца так, што ID ўводзіцца адначасова паміж праверкай часу і запісы часу» FindAsync заўсёды вяртае нулявым або юрыдычная асоба. Паралелізм канфлікт будзе адбывацца толькі тады, калі яна выдаленая або зменена паміж чэкам і захаваць
дададзена аўтар Scott Young, крыніца
Вы праверылі гэта, але хто-то ў той жа час выдалены так, SaveChanges згенеруе выключэнне
дададзена аўтар Scott Young, крыніца
але калі вы праверылі яго і не існуе, то ён будзе вяртаць 404 не знойдзены ў любым выпадку, не будзе нічога дрэннага, нават калі нехта дадаў радок з гэтым канкрэтным ідэнтыфікатарам неўзабаве пасля таго, як ... па крайняй меры, я так думаю, таму што няма ніякага іншага спосаб справіцца з гэтым
дададзена аўтар Scott Young, крыніца
@Konrad, калі <�я> ведаю, , што асноўнай запыт вы працуеце будзе марнаваць шмат часу/працэсара/памяці/і г.д. выконваючым перад адмовай, але праверка запыту можа выконвацца нашмат хутчэй, <�я>, то </я> можа варта запусціць праверку запыту, а затым ўмоўна асноўнай запыт у межах таго ж здзелкі - бібліятэка мовы праграмавання для вашай базы дадзеных павінны прадастаўляць магчымасць запуску і завяршыць здзелку. <�Б> Аднак , памятаеце, што заўчасная аптымізацыя часта марна намаганняў, таму зрабіць гэта толькі калі вы на самой справе ведаю, , што гэта неэфектыўна.
дададзена аўтар user223697, крыніца
@Konrad Мая пазіцыя заключаецца ў тым, што па змаўчанні, правільны выбар па гэта адзін запыт, які не зможа сам па сабе, і гэта <�я> асобны запыт </я> папярэдне пульсавалай падыход, які нясе цяжар доказу, каб апраўдаць сябе. Што тычыцца "стаць праблемай": так што вы <�б> з'яўляюцца <�я> з дапамогай аперацыі або <�я> у адваротным выпадку гарантуючы, што вы абаронены ад памылак ToCToU , праўда? Гэта не відавочна для мяне з кода адказваў, што вы, але калі ў вас няма, то гэта ўжо становіцца праблемай так, што бомба запаволенага дзеяння становіцца праблемай задоўга да таго, як на самой справе выбухае.
дададзена аўтар user223697, крыніца
Праверка на унікальнасць першага не ліквідуе неабходнасць апрацоўкі магчымых збояў. З іншага боку, калі дзеянне запатрабуе выканання некалькіх аперацый, правяраючы, ці ўсё маюць вялікую верагоднасць поспеху, перш чым пачаць якія-небудзь з іх часта лепш, чым выкананне дзеянняў, якія могуць <�я>, верагодна, трэба адкаціць. Выкананне пачатковых праверак не можа пазбегнуць ўсіх сітуацый, калі адкат будзе неабходны, але гэта можа дапамагчы знізіць частату такіх выпадкаў.
дададзена аўтар supercat, крыніца
«Праверка на унікальнасць, а затым ўстаноўка з'яўляецца антипаттернами» Я б не сказаў гэтага. Гэта моцна залежыць ад таго, ці можна лічыць, ніякіх іншых змен не адбываецца, і на вырабляе Ці праверка некаторы больш карысны вынік (нават проста паведамленне пра памылку, што на самой справе азначае нешта для чытача), калі ён не існуе. З базай дадзеных апрацоўкі адначасовых вэб-запытамі, няма, вы не можаце гарантаваць, іншыя змены не адбываюцца, але бываюць выпадкі, калі гэта разумнае здагадка.
дададзена аўтар jmibanez, крыніца
@Konrad Гэта было даволі значная пераробка не спадзявацца на стане застаецца нязменным. Код у пытанні быў дрэнна распрацаваны, каб пачаць з і зрабіў менавіта тое памылкі, што гэтае пытанне тычыцца. (Не прызнаючы, што неабходна для працы ў паралельным рэжыме) Калі яна была напісана і першапачаткова выпрабаванымі, распрацоўшчык быў адзіным карыстальнікам і зрабілі ўсё тэставанне ўручную, так што усё працавала нармальна. Пасля таго, як там былі толькі два карыстальнікі ў UAT ўсё стала вельмі дзіўна хутка. Спробы атрымаць блакаванне чытання працуе ў транзакцыі да працы ўжо апошняе намаганне, каб захаваць яго.
дададзена аўтар Laurens Swart, крыніца
@Konrad EF ядро ​​не будзе няяўна ставіць як чэк і ўстаўкі ў адной транзакцыі, вы павінны відавочна запытаць. Без здзелкі, праверка першага бессэнсоўная, як стан базы дадзеных можа перамыкацца паміж праверкай і ўставіць у любым выпадку. Нават з транзакцыяй, Вы не маглі б прадухіліць базу дадзеных ад змены пад нагамі. Мы пабеглі ў да праблемы некалькі гадоў таму з дапамогай EF з Oracle, дзе хоць дб падтрымлівае яго, Entity быў не выклікае замыканне прачытаных запісаў у адной транзакцыі, і толькі ўстаўка разглядаліся як транзакцыйных.
дададзена аўтар Laurens Swart, крыніца
@Konrad Калі 1 аперацыя залежыць ад слупкоў з розных табліц, то чаму б не далучыцца да іх і запытаць іх у 1 зварот у базу?
дададзена аўтар user55642, крыніца

Я думаю, што вы называеце «трываць няўдачу хутка» і тое, што я называю гэта не тое ж самае.

Распавядаючы базу дадзеных, каб зрабіць змены і рэгуляваць адмову, , што хутка. Ваш шлях складаны, павольны і не вельмі надзейны.

Гэтая тэхніка ваша не абавязкова хутка, гэта «предпечатной праверкі». Ёсць часам добрыя прычыны, але не тады, калі вы карыстаецеся базу дадзеных.

36
дададзена
Вы мяркуеце, што ваша БД захоўвае супярэчлівыя звесткі. Іншымі словамі, падобна, вы не давяраеце ў вашай БД і несупярэчлівасці дадзеных. Калі б гэта было так, то ў вас ёсць сапраўды вялікая праблема, і ваша рашэнне з'яўляецца Walkaround. Рашэнне паліятыўнай наканавана было адменена раней, чым пазней. Там могуць быць выпадкі, калі вы вымушаныя спажываць БД па-за вашага кантролю і кіравання. З іншых прыкладанняў. У тых выпадках, я лічыў бы такія запэўненні. У любым выпадку, @gnasher правоў, твой не падвядуць хутка, ці гэта не тое, што мы разумеем, як не ў стане хутка.
дададзена аўтар glacier, крыніца
Ёсць выпадкі, калі вам патрэбен 2-й запыт, калі адзін клас залежыць ад іншага, так што ў вас няма выбару ў падобных выпадках.
дададзена аўтар Scott Young, крыніца
Я думаю, што гэта таксама залежыць ад прыкладання, калі вы ствараеце яго толькі для некалькіх карыстальнікаў, то гэта не павінна мець значэнне і коды больш чытаныя з 2-запытамі.
дададзена аўтар Scott Young, крыніца
Але не тут. І запыты да базы дадзеных могуць быць вельмі разумнымі, таму я наогул не сумняваюся, што «няма выбару».
дададзена аўтар gnasher729, крыніца

Гэта пачалося ў якасці каментара, але стаў занадта вялікім.

Няма, як і іншыя адказы заявілі, гэтая мадэль не павінна выкарыстоўвацца. *

Пры працы з сістэмамі, якія выкарыстоўваюць асінхронныя кампаненты, там будзе <�моцнага> заўсёды з'яўляецца станам гонкі, дзе база дадзеных (або файлавая сістэма або іншая сістэма асінхроннай) можа змяняцца ад праверкі і змен. Праверка гэтага тыпу проста не надзейны спосаб прадухіліць тып памылкі вы не хочаце апрацоўваць.
Горш не з'яўляецца дастатковым, на першы погляд ствараецца ўражанне, што <�ет> павінен прадухіліць паўтараюцца запісу памылак дае ілжывае пачуццё бяспекі.

Вам трэба апрацоўка памылкі ў любым выпадку.

У каментарах вы спыталі, што калі вам патрэбныя дадзеныя з некалькіх крыніц.
Яшчэ No.

фундаментальны пытанне не сыходзіць, калі тое, што вы хочаце праверыць, становіцца ўсё больш складаным.

Вам усё яшчэ трэба апрацоўка памылкі ў любым выпадку.

Нават калі гэтая праверка была надзейным спосабам прадухіліць канкрэтную памылку, якую вы спрабуеце абараніцца ад, іншыя памылкі ўсё яшчэ можа адбыцца. Што адбудзецца, калі вы страціце злучэнне з базай дадзеных, або яна працуе па-за прасторы, або?

Вы вельмі верагодна, усё яшчэ патрабуецца іншы апрацоўка памылак базы дадзеных, звязаных так ці інакш. Апрацоўка гэтай канкрэтнай памылкі, верагодна, варта невялікі кавалачак яго.

Калі вам патрэбныя дадзеныя, каб вызначыць, што трэба змяніць, вы, відавочна, трэба будзе збіраць яго недзе. (У залежнасці ад таго, якія інструменты вы выкарыстоўваеце ёсць, верагодна, лепшыя спосабы, чым асобныя запыты, каб сабраць яго) Калі пры разглядзе дадзеных, якія вы сабралі, вы вызначаеце, што вам не трэба, каб зрабіць змены ў рэшце рэшт, вялікі, не робяць змяніць. Гэта вызначэнне цалкам аддзеленае ад праблем апрацоўкі памылак.

Вам усё яшчэ трэба апрацоўка памылкі ў любым выпадку.

Я ведаю, што я паўтарыцца, але я адчуваю, што вельмі важна, каб гэта ясна. Я ачысьціў гэты беспарадак раней.

Ён пацерпіць няўдачу ў рэшце рэшт. Калі ён не ў стане будзе цяжка і адымае шмат часу, каб дабрацца да ніжняй часткі. Рашэнне праблем, якія ўзнікаюць ва ўмовах гонкі цяжка. Яны не адбываюцца паслядоўна, так што гэта будзе цяжка ці нават немагчыма прайграць ў ізаляцыі. Вы не паставілі ў адпаведную апрацоўку памылак, каб пачаць з, так што вы не будзеце, верагодна, прыйдзецца шмат хадзіць на: (., Якія эй вы спрабавалі прадухіліць бачыць у першую чаргу) Можа быць справаздачу канчатковага карыстальніка нейкага загадкавага тэксту можа быць, трасіроўка стэка, які паказвае назад на гэтую функцыю, калі вы глядзіце на гэта відавочна адмаўляе памылка павінна быць нават магчыма.

* Там можа быць сапраўдная бізнес прычына для выканання гэтых праверак існуе, напрыклад, каб прадухіліць прымяненне ад дублявання дарагой працы, але гэта не з'яўляецца прыдатнай замена для правільнай апрацоўкі памылак.

14
дададзена

Хутчэй за заблытаны пытанне, але <�моцны> Ды вы павінны праверыць у першую чаргу, а не толькі апрацоўваць выключэння БД.

Перш за ўсё, у вашым прыкладзе вы на ўзроўні дадзеных, выкарыстоўваючы EF непасрэдна ў базе даных для запуску SQL. You код эквівалентны бегу

select * from children where id = x
//if no results, perform logic
insert into parents (blah)

Альтэрнатывай вы прапануеце:

insert into parents (blah)
//if exception, perform logic

Выкарыстанне выключэнняў для выканання ўмоўнай логікі з'яўляецца павольным і паўсюдна асуджаецца.

У вас ёсць ўмова гонкі і выкарыстоўваць транзакцыю. Але гэта можа быць цалкам зроблена ў кодзе.

using (var transaction = new TransactionScope())
{
    var child = await _db.Children.FindAsync(parent.ChildId);
    if (child == null) 
    {
       return NotFound($"Child with id {parent.ChildId} could not be found.");
    }

    _db.Parents.Add(parent);    
    await _db.SaveChangesAsync();        
    transaction.Complete();

    return parent;
}

Галоўнае, каб спытаць сябе:

<�Р> "Ці чакаеце вы адбыцца такая сітуацыя?"

Калі няма, то вядома, ўставіць прэч і кінуць выключэнне. Але проста апрацаваць выключэнне, як і любы іншы памылкі, якія могуць паўстаць.

Калі вы чакаеце, што гэта адбудзецца, то гэта не з'яўляецца выключным, і вы павінны праверыць, каб убачыць, калі дзіця існуе першы, адказваючы з адпаведным дружалюбным паведамленнем, калі ён гэтага не робіць.

Edit - There's a lot of controversy over this it seems. Before you downvote consider:

А. Што рабіць, калі два FK абмежаванні. Вы б абараняеце разборы паведамлення аб выключэнні для працы, які аб'ект адсутнічае?

B. Калі ў вас ёсць промах, толькі адзін SQL аператар выконваецца. Гэта толькі хіты, якія бяруць на сябе дадатковыя выдаткі другога запыту.

C. Звычайна Id будзе сурагатным ключ, гэта цяжка ўявіць сабе сітуацыю, калі вы ведаеце, адзін і вы не вельмі ўпэўненыя, што гэта на БД. Праверка будзе няцотнай. Але што, калі яго натуральны ключ карыстальнік надрукаваў? Гэта можа мець высокі шанц не прысутнічаючы

3
дададзена
Каментары не для шырокага абмеркавання; гэтая размова была пераехаў у чат .
дададзена аўтар maple_shaft, крыніца

Я думаю, што другасная рэч, каб адзначыць тут - адна з прычын, чаму вы хочаце гэта так, што вы можаце фарматаваць паведамленне пра памылку для карыстальніка, каб убачыць.

Я настойліва рэкамендую вам:

а) паказаць канчатковаму карыстачу той жа агульнае паведамленне пра памылку для кожны памылка, што адбываецца.

б) рэгістраваць фактычнае выключэнне недзе, што толькі распрацоўшчыкі могуць атрымаць доступ (калі на сэрвэры) або дзе-тое, што можа быць пасланы да вас інструменты справаздачнасці памылак (калі кліент разгорнуты)

в) не спрабуйце фарматаваць звесткі аб выключэнні памылак, што пры ўваходзе, калі вы не можаце дадаць больш карыснай інфармацыі. Вы не хочаце, каб выпадкова «адфарматаваны» прэч адзін кавалак карыснай інфармацыі, якую вы змаглі б выкарыстоўваць для адсочвання праблемы ўніз.


Карацей кажучы - выключэння поўна вельмі карыснай тэхнічнай інфармацыі. Нічога з гэтага не павінна быць для канчатковага карыстальніка, і вы страціце гэтую інфармацыю на свой страх і рызыка.

2
дададзена
«Паказаць канчатковаму карыстачу ж агульнае паведамленне пра памылку для кожнай памылкі, што адбываецца.» што было галоўнай прычынай, фарматаванне выключэнні для канчатковага карыстальніка выглядае як жудасная рэч, каб зрабіць ..
дададзена аўтар Scott Young, крыніца
У любой разумнай сістэме базы дадзеных, вы павінны быць у стане праграмна высветліць, чаму-то не атрымалася. Гэта не павінна быць неабходна разабраць паведамленне аб выключэнні. І ў больш агульным плане: хто кажа, што паведамленне пра памылку павінна быць адлюстравана карыстачу на ўсіх? Вы можаце праваліць першую ўстаўку і паўторыце у цыкле, пакуль не атрымаецца (або да некаторага мяжы паўторных спробаў або часу). І на самай справе, страта магутнасці, а-паўторы з'яўляецца тое, што вы будзеце жадаць, каб рэалізаваць у канчатковым выніку так ці інакш.
дададзена аўтар DWGKNZ, крыніца