| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398 |
- //------------------------------------------------------------------------------
- // <copyright file="DataTable.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- // <owner current="true" primary="true">[....]</owner>
- // <owner current="true" primary="false">[....]</owner>
- //------------------------------------------------------------------------------
- namespace System.Data {
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Diagnostics;
- using System.Globalization;
- using System.IO;
- using System.Runtime.Serialization;
- using System.Text;
- using System.Threading;
- using System.Xml;
- using System.Xml.Schema;
- using System.Xml.Serialization;
- using System.Data.Common;
- using System.Runtime.Versioning;
- using System.Runtime.CompilerServices;
- /// <devdoc>
- /// <para>Represents one table of in-memory data.</para>
- /// </devdoc>
- [
- ToolboxItem(false),
- DesignTimeVisible(false),
- DefaultProperty("TableName"),
- Editor("Microsoft.VSDesigner.Data.Design.DataTableEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing),
- DefaultEvent("RowChanging"),
- XmlSchemaProvider("GetDataTableSchema"),
- Serializable
- ]
- public class DataTable : MarshalByValueComponent, System.ComponentModel.IListSource, ISupportInitializeNotification, ISerializable, IXmlSerializable{
- private DataSet dataSet;
- private DataView defaultView = null;
- // rows
- /// <summary>
- /// Monotonically increasing number representing the order <see cref="DataRow"/> have been added to <see cref="DataRowCollection"/>.
- /// </summary>
- /// <remarks>This limits <see cref="DataRowCollection.Add(DataRow)"/> to <see cref="Int32.MaxValue"/> operations.</remarks>
- internal long nextRowID;
- internal readonly DataRowCollection rowCollection;
- // columns
- internal readonly DataColumnCollection columnCollection;
- // constraints
- private readonly ConstraintCollection constraintCollection;
- //SimpleContent implementation
- private int elementColumnCount = 0;
- // relations
- internal DataRelationCollection parentRelationsCollection;
- internal DataRelationCollection childRelationsCollection;
- // RecordManager
- internal readonly RecordManager recordManager;
- // index mgmt
- internal readonly List<Index> indexes;
- private List<Index> shadowIndexes;
- private int shadowCount;
- // props
- internal PropertyCollection extendedProperties = null;
- private string tableName = "";
- internal string tableNamespace = null;
- private string tablePrefix = "";
- internal DataExpression displayExpression;
- internal bool fNestedInDataset = true;
- // globalization stuff
- private CultureInfo _culture;
- private bool _cultureUserSet;
- private CompareInfo _compareInfo;
- private CompareOptions _compareFlags = CompareOptions.IgnoreCase | CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth;
- private IFormatProvider _formatProvider;
- private StringComparer _hashCodeProvider;
- private bool _caseSensitive;
- private bool _caseSensitiveUserSet;
- // XML properties
- internal string encodedTableName; // For XmlDataDocument only
- internal DataColumn xmlText; // text values of a complex xml element
- internal DataColumn _colUnique;
- internal bool textOnly = false; // the table has only text value with possible attributes
- internal decimal minOccurs = 1; // default = 1
- internal decimal maxOccurs = 1; // default = 1
- internal bool repeatableElement = false;
- private object typeName = null;
- // primary key info
- private readonly static Int32[] zeroIntegers = new Int32[0];
- internal readonly static DataColumn[] zeroColumns = new DataColumn[0];
- internal readonly static DataRow[] zeroRows = new DataRow[0];
- internal UniqueConstraint primaryKey;
- internal readonly static IndexField[] zeroIndexField = new IndexField[0];
- internal IndexField[] _primaryIndex = zeroIndexField;
- private DataColumn[] delayedSetPrimaryKey = null;
- // Loading Schema and/or Data related optimization
- private Index loadIndex;
- private Index loadIndexwithOriginalAdded = null;
- private Index loadIndexwithCurrentDeleted = null;
- private int _suspendIndexEvents;
- private bool savedEnforceConstraints = false;
- private bool inDataLoad = false;
- private bool initialLoad;
- private bool schemaLoading = false;
- private bool enforceConstraints = true;
- internal bool _suspendEnforceConstraints = false;
- protected internal bool fInitInProgress = false;
- private bool inLoad = false;
- internal bool fInLoadDiffgram = false;
- private byte _isTypedDataTable; // 0 == unknown, 1 = yes, 2 = No
- private DataRow[] EmptyDataRowArray;
- // Property Descriptor Cache for DataBinding
- private PropertyDescriptorCollection propertyDescriptorCollectionCache = null;
- // Cache for relation that has this table as nested child table.
- private static readonly DataRelation[] EmptyArrayDataRelation = new DataRelation[0];
- private DataRelation[] _nestedParentRelations = EmptyArrayDataRelation;
- // Dependent column list for expression evaluation
- internal List<DataColumn> dependentColumns = null;
- // events
- private bool mergingData = false;
- private DataRowChangeEventHandler onRowChangedDelegate;
- private DataRowChangeEventHandler onRowChangingDelegate;
- private DataRowChangeEventHandler onRowDeletingDelegate;
- private DataRowChangeEventHandler onRowDeletedDelegate;
- private DataColumnChangeEventHandler onColumnChangedDelegate;
- private DataColumnChangeEventHandler onColumnChangingDelegate;
- private DataTableClearEventHandler onTableClearingDelegate;
- private DataTableClearEventHandler onTableClearedDelegate;
- private DataTableNewRowEventHandler onTableNewRowDelegate;
- private PropertyChangedEventHandler onPropertyChangingDelegate;
- private System.EventHandler onInitialized;
- // misc
- private readonly DataRowBuilder rowBuilder;
- private const String KEY_XMLSCHEMA = "XmlSchema";
- private const String KEY_XMLDIFFGRAM = "XmlDiffGram";
- private const String KEY_NAME = "TableName";
- internal readonly List<DataView> delayedViews = new List<DataView>();
- private readonly List<DataViewListener> _dataViewListeners = new List<DataViewListener>();
- // private bool serializeHierarchy = false;
- internal Hashtable rowDiffId = null;
- internal readonly ReaderWriterLock indexesLock = new ReaderWriterLock();
- internal int ukColumnPositionForInference= -1;
- // default remoting format is Xml
- private SerializationFormat _remotingFormat = SerializationFormat.Xml;
- private static int _objectTypeCount; // Bid counter
- private readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);
- /// <devdoc>
- /// <para>Initializes a new instance of the <see cref='System.Data.DataTable'/> class with no arguments.</para>
- /// </devdoc>
- public DataTable() {
- GC.SuppressFinalize(this);
- Bid.Trace("<ds.DataTable.DataTable|API> %d#\n", ObjectID);
- nextRowID = 1;
- recordManager = new RecordManager(this);
- _culture = CultureInfo.CurrentCulture;
- this.columnCollection = new DataColumnCollection(this);
- this.constraintCollection = new ConstraintCollection(this);
- this.rowCollection = new DataRowCollection(this);
- this.indexes = new List<Index>();
- rowBuilder = new DataRowBuilder(this, -1);
- }
- /// <devdoc>
- /// <para>Intitalizes a new instance of the <see cref='System.Data.DataTable'/> class with the specified table
- /// name.</para>
- /// </devdoc>
- public DataTable(string tableName) : this() {
- this.tableName = tableName == null ? "" : tableName;
- }
- public DataTable(string tableName, string tableNamespace) : this(tableName) {
- this.Namespace = tableNamespace;
- }
- // Deserialize the table from binary/xml stream.
- protected DataTable(SerializationInfo info, StreamingContext context) : this()
- {
- bool isSingleTable = context.Context != null ? Convert.ToBoolean(context.Context, CultureInfo.InvariantCulture) : true;
- SerializationFormat remotingFormat = SerializationFormat.Xml;
- SerializationInfoEnumerator e = info.GetEnumerator();
- while (e.MoveNext()) {
- switch(e.Name) {
- case "DataTable.RemotingFormat" : //DataTable.RemotingFormat does not exist in V1/V1.1 versions
- remotingFormat = (SerializationFormat)e.Value;
- break;
- }
- }
- DeserializeDataTable(info, context, isSingleTable, remotingFormat);
- }
- [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Flags=System.Security.Permissions.SecurityPermissionFlag.SerializationFormatter)]
- public virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
- SerializationFormat remotingFormat = RemotingFormat;
- bool isSingleTable = context.Context != null ? Convert.ToBoolean(context.Context, CultureInfo.InvariantCulture) : true;
- SerializeDataTable(info, context, isSingleTable, remotingFormat);
- }
- // Serialize the table schema and data.
- private void SerializeDataTable(SerializationInfo info, StreamingContext context, bool isSingleTable, SerializationFormat remotingFormat) {
- info.AddValue("DataTable.RemotingVersion", new Version(2, 0));
- // SqlHotFix 299, SerializationFormat enumeration types don't exist in V1.1 SP1
- if (SerializationFormat.Xml != remotingFormat) {
- info.AddValue("DataTable.RemotingFormat", remotingFormat);
- }
- if (remotingFormat != SerializationFormat.Xml) {//Binary
- SerializeTableSchema(info, context, isSingleTable);
- if (isSingleTable) {
- SerializeTableData(info, context, 0);
- }
- } else {//XML/V1.0/V1.1
- string tempDSNamespace = "";
- Boolean fCreatedDataSet = false;
- if (dataSet == null) {
- DataSet ds = new DataSet("tmpDataSet");
- // if user set values on DataTable, it isn't necessary
- // to set them on the DataSet because they won't be inherited
- // but it is simpler to set them in both places
- // if user did not set values on DataTable, it is required
- // to set them on the DataSet so the table will inherit
- // the value already on the Datatable
- ds.SetLocaleValue(_culture, _cultureUserSet);
- ds.CaseSensitive = this.CaseSensitive;
- ds.namespaceURI = this.Namespace;
- Debug.Assert(ds.RemotingFormat == SerializationFormat.Xml, "RemotingFormat must be SerializationFormat.Xml");
- ds.Tables.Add(this);
- fCreatedDataSet = true;
- } else {
- tempDSNamespace = this.DataSet.Namespace;
- this.DataSet.namespaceURI = this.Namespace; //this.DataSet.Namespace = this.Namespace; ??
- }
- info.AddValue(KEY_XMLSCHEMA, dataSet.GetXmlSchemaForRemoting(this));
- info.AddValue(KEY_XMLDIFFGRAM, dataSet.GetRemotingDiffGram(this));
- if (fCreatedDataSet) {
- dataSet.Tables.Remove(this);
- }
- else{
- dataSet.namespaceURI = tempDSNamespace;
- }
- }
- }
- // Deserialize the table schema and data.
- internal void DeserializeDataTable(SerializationInfo info, StreamingContext context, bool isSingleTable, SerializationFormat remotingFormat) {
- if (remotingFormat != SerializationFormat.Xml) {//Binary
- DeserializeTableSchema(info, context, isSingleTable);
- if (isSingleTable) {
- DeserializeTableData(info, context, 0);
- this.ResetIndexes();
- }
- } else {//XML/V1.0/V1.1
- string strSchema = (String)info.GetValue(KEY_XMLSCHEMA, typeof(System.String));
- string strData = (String)info.GetValue(KEY_XMLDIFFGRAM, typeof(System.String));
- if (strSchema != null) {
- DataSet ds = new DataSet();
- // fxcop: ReadXmlSchema will provide the CaseSensitive, Locale, Namespace information
- ds.ReadXmlSchema(new XmlTextReader( new StringReader( strSchema ) ) );
- Debug.Assert(ds.Tables.Count == 1, "There should be exactly 1 table here");
- DataTable table = ds.Tables[0];
- table.CloneTo(this, null, false);// WebData 111656
- //this is to avoid the cascading rules in the namespace
- this.Namespace = table.Namespace;
- if (strData != null) {
- ds.Tables.Remove(ds.Tables[0]);
- ds.Tables.Add(this);
- ds.ReadXml(new XmlTextReader( new StringReader( strData ) ), XmlReadMode.DiffGram);
- ds.Tables.Remove(this);
- }
- }
- }
- }
- // Serialize the columns
- internal void SerializeTableSchema(SerializationInfo info, StreamingContext context, bool isSingleTable) {
- //DataTable basic properties
- info.AddValue("DataTable.TableName", TableName);
- info.AddValue("DataTable.Namespace", Namespace);
- info.AddValue("DataTable.Prefix", Prefix);
- info.AddValue("DataTable.CaseSensitive", _caseSensitive);
- info.AddValue("DataTable.caseSensitiveAmbient", !_caseSensitiveUserSet);
- info.AddValue("DataTable.LocaleLCID", Locale.LCID);
- info.AddValue("DataTable.MinimumCapacity", recordManager.MinimumCapacity);
- //info.AddValue("DataTable.DisplayExpression", DisplayExpression);
- //DataTable state internal properties
- info.AddValue("DataTable.NestedInDataSet", fNestedInDataset);
- info.AddValue("DataTable.TypeName", TypeName.ToString());
- info.AddValue("DataTable.RepeatableElement", repeatableElement);
- //ExtendedProperties
- info.AddValue("DataTable.ExtendedProperties", ExtendedProperties);
- //Columns
- info.AddValue("DataTable.Columns.Count", Columns.Count);
- //Check for closure of expression in case of single table.
- if (isSingleTable) {
- List<DataTable> list = new List<DataTable>();
- list.Add(this);
- if (!CheckForClosureOnExpressionTables(list))
- throw ExceptionBuilder.CanNotRemoteDataTable();
- }
- IFormatProvider formatProvider = CultureInfo.InvariantCulture;
- for (int i = 0; i < Columns.Count; i++) {
- //DataColumn basic properties
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.ColumnName", i), Columns[i].ColumnName);
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.Namespace", i), Columns[i]._columnUri);
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.Prefix", i), Columns[i].Prefix);
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.ColumnMapping", i), Columns[i].ColumnMapping);
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.AllowDBNull", i), Columns[i].AllowDBNull);
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.AutoIncrement", i), Columns[i].AutoIncrement);
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.AutoIncrementStep", i), Columns[i].AutoIncrementStep);
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.AutoIncrementSeed", i), Columns[i].AutoIncrementSeed);
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.Caption", i), Columns[i].Caption);
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.DefaultValue", i), Columns[i].DefaultValue);
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.ReadOnly", i), Columns[i].ReadOnly);
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.MaxLength", i), Columns[i].MaxLength);
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.DataType", i), Columns[i].DataType);
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.XmlDataType", i), Columns[i].XmlDataType);
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.SimpleType", i), Columns[i].SimpleType);
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.DateTimeMode", i), Columns[i].DateTimeMode);
- //DataColumn internal state properties
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.AutoIncrementCurrent", i), Columns[i].AutoIncrementCurrent);
- //Expression
- if (isSingleTable) {
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.Expression", i), Columns[i].Expression);
- }
- //ExtendedProperties
- info.AddValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.ExtendedProperties", i), Columns[i].extendedProperties);
- }
- //Constraints
- if (isSingleTable) {
- SerializeConstraints(info, context, 0, false);
- }
- }
- // Deserialize all the Columns
- internal void DeserializeTableSchema(SerializationInfo info, StreamingContext context, bool isSingleTable) {
- //DataTable basic properties
- tableName = info.GetString("DataTable.TableName");
- tableNamespace = info.GetString("DataTable.Namespace");
- tablePrefix = info.GetString("DataTable.Prefix");
- bool caseSensitive = info.GetBoolean("DataTable.CaseSensitive");
- SetCaseSensitiveValue(caseSensitive, true, false);
- _caseSensitiveUserSet = !info.GetBoolean("DataTable.caseSensitiveAmbient");
- int lcid = (int)info.GetValue("DataTable.LocaleLCID", typeof(int));
- CultureInfo culture = new CultureInfo(lcid);
- SetLocaleValue(culture, true, false);
- _cultureUserSet = true;
- MinimumCapacity = info.GetInt32("DataTable.MinimumCapacity");
- //DisplayExpression = info.GetString("DataTable.DisplayExpression");
- //DataTable state internal properties
- fNestedInDataset = (bool) info.GetBoolean("DataTable.NestedInDataSet");
- string tName = info.GetString("DataTable.TypeName");
- typeName = new XmlQualifiedName(tName);
- repeatableElement = info.GetBoolean("DataTable.RepeatableElement");
- //ExtendedProperties
- extendedProperties = (PropertyCollection) info.GetValue("DataTable.ExtendedProperties", typeof(PropertyCollection));
- //Columns
- int colCount = info.GetInt32("DataTable.Columns.Count");
- string [] expressions = new string[colCount];
- Debug.Assert(Columns.Count == 0, "There is column in Table");
- IFormatProvider formatProvider = CultureInfo.InvariantCulture;
- for (int i = 0; i < colCount; i++) {
- DataColumn dc = new DataColumn();
- //DataColumn public state properties
- dc.ColumnName = info.GetString(String.Format(formatProvider, "DataTable.DataColumn_{0}.ColumnName", i));
- dc._columnUri = info.GetString(String.Format(formatProvider, "DataTable.DataColumn_{0}.Namespace", i));
- dc.Prefix = info.GetString(String.Format(formatProvider, "DataTable.DataColumn_{0}.Prefix", i));
- dc.DataType = (Type) info.GetValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.DataType", i), typeof(Type));
- dc.XmlDataType = (string) info.GetValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.XmlDataType", i), typeof(string));
- dc.SimpleType = (SimpleType) info.GetValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.SimpleType", i), typeof(SimpleType));
- dc.ColumnMapping = (MappingType) info.GetValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.ColumnMapping", i), typeof(MappingType));
- dc.DateTimeMode = (DataSetDateTime) info.GetValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.DateTimeMode", i), typeof(DataSetDateTime));
- dc.AllowDBNull = info.GetBoolean(String.Format(formatProvider, "DataTable.DataColumn_{0}.AllowDBNull", i));
- dc.AutoIncrement = info.GetBoolean(String.Format(formatProvider, "DataTable.DataColumn_{0}.AutoIncrement", i));
- dc.AutoIncrementStep = info.GetInt64(String.Format(formatProvider, "DataTable.DataColumn_{0}.AutoIncrementStep", i));
- dc.AutoIncrementSeed = info.GetInt64(String.Format(formatProvider, "DataTable.DataColumn_{0}.AutoIncrementSeed", i));
- dc.Caption = info.GetString(String.Format(formatProvider, "DataTable.DataColumn_{0}.Caption", i));
- dc.DefaultValue = info.GetValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.DefaultValue", i), typeof(object));
- dc.ReadOnly = info.GetBoolean(String.Format(formatProvider, "DataTable.DataColumn_{0}.ReadOnly", i));
- dc.MaxLength= info.GetInt32(String.Format(formatProvider, "DataTable.DataColumn_{0}.MaxLength", i));
- //DataColumn internal state properties
- dc.AutoIncrementCurrent = info.GetValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.AutoIncrementCurrent", i), typeof(object));
- //Expression
- if (isSingleTable) {
- expressions[i] = info.GetString(String.Format(formatProvider, "DataTable.DataColumn_{0}.Expression", i));
- }
- //ExtendedProperties
- dc.extendedProperties = (PropertyCollection) info.GetValue(String.Format(formatProvider, "DataTable.DataColumn_{0}.ExtendedProperties", i), typeof(PropertyCollection));
- Columns.Add(dc);
- }
- if (isSingleTable) {
- for(int i = 0; i < colCount; i++) {
- if (expressions[i] != null) {
- Columns[i].Expression = expressions[i];
- }
- }
- }
- //Constraints
- if (isSingleTable) {
- DeserializeConstraints(info, context, /*table index */ 0, /* serialize all constraints */false);// since single table, send table index as 0, meanwhile passing
- // false for 'allConstraints' means, handle all the constraint related to the table
- }
- }
- /*
- Serialize constraints availabe on the table - note this function is marked internal because it is called by the DataSet deserializer.
- ***Schema for Serializing ArrayList of Constraints***
- Unique Constraint - ["U"]->[constraintName]->[columnIndexes]->[IsPrimaryKey]->[extendedProperties]
- Foriegn Key Constraint - ["F"]->[constraintName]->[parentTableIndex, parentcolumnIndexes]->[childTableIndex, childColumnIndexes]->[AcceptRejectRule, UpdateRule, DeleteRule]->[extendedProperties]
- */
- internal void SerializeConstraints(SerializationInfo info, StreamingContext context, int serIndex, bool allConstraints) {
- if (allConstraints) {
- Debug.Assert(DataSet != null);
- }
- ArrayList constraintList = new ArrayList();
- for (int i = 0; i < Constraints.Count; i++) {
- Constraint c = Constraints[i];
- UniqueConstraint uc = c as UniqueConstraint;
- if (uc != null) {
- int[] colInfo = new int[uc.Columns.Length];
- for (int j = 0; j < colInfo.Length; j++) {
- colInfo[j] = uc.Columns[j].Ordinal;
- }
- ArrayList list = new ArrayList();
- list.Add("U");
- list.Add(uc.ConstraintName);
- list.Add(colInfo);
- list.Add(uc.IsPrimaryKey);
- list.Add(uc.ExtendedProperties);
- constraintList.Add(list);
- } else {
- ForeignKeyConstraint fk = c as ForeignKeyConstraint;
- Debug.Assert(fk != null);
- bool shouldSerialize = (allConstraints == true) || (fk.Table == this && fk.RelatedTable == this);
- if (shouldSerialize) {
- int[] parentInfo = new int[fk.RelatedColumns.Length + 1];
- parentInfo[0] = allConstraints ? this.DataSet.Tables.IndexOf(fk.RelatedTable) : 0;
- for (int j = 1; j < parentInfo.Length; j++) {
- parentInfo[j] = fk.RelatedColumns[j - 1].Ordinal;
- }
- int[] childInfo = new int[fk.Columns.Length + 1];
- childInfo[0] = allConstraints ? this.DataSet.Tables.IndexOf(fk.Table) : 0 ; //Since the constraint is on the current table, this is the child table.
- for (int j = 1; j < childInfo.Length; j++) {
- childInfo[j] = fk.Columns[j - 1].Ordinal;
- }
- ArrayList list = new ArrayList();
- list.Add("F");
- list.Add(fk.ConstraintName);
- list.Add(parentInfo);
- list.Add(childInfo);
- list.Add(new int[] { (int) fk.AcceptRejectRule, (int) fk.UpdateRule, (int) fk.DeleteRule });
- list.Add(fk.ExtendedProperties);
- constraintList.Add(list);
- }
- }
- }
- info.AddValue(String.Format(CultureInfo.InvariantCulture, "DataTable_{0}.Constraints", serIndex), constraintList);
- }
- /*
- Deserialize the constraints on the table.
- ***Schema for Serializing ArrayList of Constraints***
- Unique Constraint - ["U"]->[constraintName]->[columnIndexes]->[IsPrimaryKey]->[extendedProperties]
- Foriegn Key Constraint - ["F"]->[constraintName]->[parentTableIndex, parentcolumnIndexes]->[childTableIndex, childColumnIndexes]->[AcceptRejectRule, UpdateRule, DeleteRule]->[extendedProperties]
- */
- internal void DeserializeConstraints(SerializationInfo info, StreamingContext context, int serIndex, bool allConstraints) {
- ArrayList constraintList = (ArrayList) info.GetValue(String.Format(CultureInfo.InvariantCulture, "DataTable_{0}.Constraints", serIndex), typeof(ArrayList));
- foreach (ArrayList list in constraintList) {
- string con = (string) list[0];
- if (con.Equals("U")) { //Unique Constraints
- string constraintName = (string) list[1];
- int[] keyColumnIndexes = (int[]) list[2];
- bool isPrimaryKey = (bool) list[3];
- PropertyCollection extendedProperties = (PropertyCollection) list[4];
- DataColumn[] keyColumns = new DataColumn[keyColumnIndexes.Length];
- for (int i = 0; i < keyColumnIndexes.Length; i++) {
- keyColumns[i] = Columns[keyColumnIndexes[i]];
- }
- //Create the constraint.
- UniqueConstraint uc = new UniqueConstraint(constraintName, keyColumns, isPrimaryKey);
- uc.extendedProperties = extendedProperties;
- //Add the unique constraint and it will in turn set the primary keys also if needed.
- Constraints.Add(uc);
- } else { //ForeignKeyConstraints
- Debug.Assert(con.Equals("F"));
- string constraintName = (string) list[1];
- int[] parentInfo = (int[]) list[2];
- int[] childInfo = (int[]) list[3];
- int[] rules = (int[]) list[4];
- PropertyCollection extendedProperties = (PropertyCollection) list[5];
- //ParentKey Columns.
- DataTable parentTable = (allConstraints == false) ? this : this.DataSet.Tables[parentInfo[0]];
- DataColumn[] parentkeyColumns = new DataColumn[parentInfo.Length - 1];
- for (int i = 0; i < parentkeyColumns.Length; i++) {
- parentkeyColumns[i] = parentTable.Columns[parentInfo[i + 1]];
- }
- //ChildKey Columns.
- DataTable childTable = (allConstraints == false) ? this : this.DataSet.Tables[childInfo[0]];
- DataColumn[] childkeyColumns = new DataColumn[childInfo.Length - 1];
- for (int i = 0; i < childkeyColumns.Length; i++) {
- childkeyColumns[i] = childTable.Columns[childInfo[i + 1]];
- }
- //Create the Constraint.
- ForeignKeyConstraint fk = new ForeignKeyConstraint(constraintName, parentkeyColumns, childkeyColumns);
- fk.AcceptRejectRule = (AcceptRejectRule) rules[0];
- fk.UpdateRule = (Rule) rules[1];
- fk.DeleteRule = (Rule) rules[2];
- fk.extendedProperties = extendedProperties;
- //Add just the foreign key constraint without creating unique constraint.
- Constraints.Add(fk, false);
- }
- }
- }
- // Serialize the expressions on the table - Marked internal so that DataSet deserializer can call into this
- internal void SerializeExpressionColumns(SerializationInfo info, StreamingContext context, int serIndex) {
- int colCount = Columns.Count;
- for (int i = 0; i < colCount; i++) {
- info.AddValue(String.Format(CultureInfo.InvariantCulture, "DataTable_{0}.DataColumn_{1}.Expression", serIndex, i), Columns[i].Expression);
- }
- }
- // Deserialize the expressions on the table - Marked internal so that DataSet deserializer can call into this
- internal void DeserializeExpressionColumns(SerializationInfo info, StreamingContext context, int serIndex) {
- int colCount = Columns.Count;
- for (int i = 0; i < colCount; i++) {
- string expr = info.GetString(String.Format(CultureInfo.InvariantCulture, "DataTable_{0}.DataColumn_{1}.Expression", serIndex, i));
- if (0 != expr.Length) {
- Columns[i].Expression = expr;
- }
- }
- }
- // Serialize all the Rows.
- internal void SerializeTableData(SerializationInfo info, StreamingContext context, int serIndex) {
- //Cache all the column count, row count
- int colCount = Columns.Count;
- int rowCount = Rows.Count;
- int modifiedRowCount = 0;
- int editRowCount = 0;
- //Compute row states and assign the bits accordingly - 00[Unchanged], 01[Added], 10[Modifed], 11[Deleted]
- BitArray rowStates = new BitArray(rowCount * 3, false); //All bit flags are set to false on initialization of the BitArray.
- for (int i = 0; i < rowCount; i++) {
- int bitIndex = i * 3;
- DataRow row = Rows[i];
- DataRowState rowState = row.RowState;
- switch (rowState) {
- case DataRowState.Unchanged:
- //rowStates[bitIndex] = false;
- //rowStates[bitIndex + 1] = false;
- break;
- case DataRowState.Added:
- //rowStates[bitIndex] = false;
- rowStates[bitIndex + 1] = true;
- break;
- case DataRowState.Modified:
- rowStates[bitIndex] = true;
- //rowStates[bitIndex + 1] = false;
- modifiedRowCount++;
- break;
- case DataRowState.Deleted:
- rowStates[bitIndex] = true;
- rowStates[bitIndex + 1] = true;
- break;
- default:
- throw ExceptionBuilder.InvalidRowState(rowState);
- }
- if (-1 != row.tempRecord) {
- rowStates[bitIndex + 2] = true;
- editRowCount++;
- }
- }
- //Compute the actual storage records that need to be created.
- int recordCount = rowCount + modifiedRowCount + editRowCount;
- //Create column storages.
- ArrayList storeList = new ArrayList();
- ArrayList nullbitList = new ArrayList();
- if (recordCount > 0) { //Create the storage only if have records.
- for (int i = 0; i < colCount; i++) {
- object store = Columns[i].GetEmptyColumnStore(recordCount);
- storeList.Add(store);
- BitArray nullbits = new BitArray(recordCount);
- nullbitList.Add(nullbits);
- }
- }
- //Copy values into column storages
- int recordsConsumed = 0;
- Hashtable rowErrors = new Hashtable();
- Hashtable colErrors = new Hashtable();
- for (int i = 0; i < rowCount; i++) {
- int recordsPerRow = Rows[i].CopyValuesIntoStore(storeList, nullbitList, recordsConsumed);
- GetRowAndColumnErrors(i, rowErrors, colErrors);
- recordsConsumed += recordsPerRow;
- }
- IFormatProvider formatProvider = CultureInfo.InvariantCulture;
- //Serialize all the computed values.
- info.AddValue(String.Format(formatProvider, "DataTable_{0}.Rows.Count", serIndex), rowCount);
- info.AddValue(String.Format(formatProvider, "DataTable_{0}.Records.Count", serIndex), recordCount);
- info.AddValue(String.Format(formatProvider, "DataTable_{0}.RowStates", serIndex), rowStates);
- info.AddValue(String.Format(formatProvider, "DataTable_{0}.Records", serIndex), storeList);
- info.AddValue(String.Format(formatProvider, "DataTable_{0}.NullBits", serIndex), nullbitList);
- info.AddValue(String.Format(formatProvider, "DataTable_{0}.RowErrors", serIndex), rowErrors);
- info.AddValue(String.Format(formatProvider, "DataTable_{0}.ColumnErrors", serIndex), colErrors);
- }
- // Deserialize all the Rows.
- internal void DeserializeTableData(SerializationInfo info, StreamingContext context, int serIndex) {
- bool enforceConstraintsOrg = enforceConstraints;
- bool inDataLoadOrg = inDataLoad;
- try {
- enforceConstraints = false;
- inDataLoad = true;
- IFormatProvider formatProvider = CultureInfo.InvariantCulture;
- int rowCount = info.GetInt32(String.Format(formatProvider, "DataTable_{0}.Rows.Count", serIndex));
- int recordCount = info.GetInt32(String.Format(formatProvider, "DataTable_{0}.Records.Count", serIndex));
- BitArray rowStates = (BitArray) info.GetValue(String.Format(formatProvider, "DataTable_{0}.RowStates", serIndex), typeof(BitArray));
- ArrayList storeList = (ArrayList) info.GetValue(String.Format(formatProvider, "DataTable_{0}.Records", serIndex), typeof(ArrayList));
- ArrayList nullbitList = (ArrayList) info.GetValue(String.Format(formatProvider, "DataTable_{0}.NullBits", serIndex), typeof(ArrayList));
- Hashtable rowErrors = (Hashtable) info.GetValue(String.Format(formatProvider, "DataTable_{0}.RowErrors", serIndex), typeof(Hashtable));
- rowErrors.OnDeserialization(this);//OnDeSerialization must be called since the hashtable gets deserialized after the whole graph gets deserialized
- Hashtable colErrors = (Hashtable) info.GetValue(String.Format(formatProvider, "DataTable_{0}.ColumnErrors", serIndex), typeof(Hashtable));
- colErrors.OnDeserialization(this);//OnDeSerialization must be called since the hashtable gets deserialized after the whole graph gets deserialized
- if (recordCount <= 0) { //No need for deserialization of the storage and errors if there are no records.
- return;
- }
- //Point the record manager storage to the deserialized values.
- for (int i = 0; i < Columns.Count; i++) {
- Columns[i].SetStorage(storeList[i], (BitArray) nullbitList[i]);
- }
- //Create rows and set the records appropriately.
- int recordIndex = 0;
- DataRow[] rowArr = new DataRow[recordCount];
- for (int i = 0; i < rowCount; i++) {
- //Create a new row which sets old and new records to -1.
- DataRow row = NewEmptyRow();
- rowArr[recordIndex] = row;
- int bitIndex = i * 3;
- switch (ConvertToRowState(rowStates, bitIndex)) {
- case DataRowState.Unchanged:
- row.oldRecord = recordIndex;
- row.newRecord = recordIndex;
- recordIndex += 1;
- break;
- case DataRowState.Added:
- row.oldRecord = -1;
- row.newRecord = recordIndex;
- recordIndex += 1;
- break;
- case DataRowState.Modified:
- row.oldRecord = recordIndex;
- row.newRecord = recordIndex + 1;
- rowArr[recordIndex + 1] = row;
- recordIndex += 2;
- break;
- case DataRowState.Deleted:
- row.oldRecord = recordIndex;
- row.newRecord = -1;
- recordIndex += 1;
- break;
- }
- if (rowStates[bitIndex + 2]) {
- row.tempRecord = recordIndex;
- rowArr[recordIndex] = row;
- recordIndex += 1;
- } else {
- row.tempRecord = -1;
- }
- Rows.ArrayAdd(row);
- row.rowID = nextRowID;
- nextRowID++;
- ConvertToRowError(i, rowErrors, colErrors);
- }
- recordManager.SetRowCache(rowArr);
- ResetIndexes();
- } finally {
- enforceConstraints = enforceConstraintsOrg;
- inDataLoad = inDataLoadOrg;
- }
- }
- // Constructs the RowState from the two bits in the bitarray.
- private DataRowState ConvertToRowState(BitArray bitStates, int bitIndex) {
- Debug.Assert(bitStates != null);
- Debug.Assert(bitStates.Length > bitIndex);
- bool b1 = bitStates[bitIndex];
- bool b2 = bitStates[bitIndex + 1];
- if (!b1 && !b2) {
- return DataRowState.Unchanged;
- } else if (!b1 && b2) {
- return DataRowState.Added;
- } else if (b1 && !b2) {
- return DataRowState.Modified;
- } else if (b1 && b2) {
- return DataRowState.Deleted;
- } else {
- throw ExceptionBuilder.InvalidRowBitPattern();
- }
- }
- // Get the error on the row and columns - Marked internal so that DataSet deserializer can call into this
- internal void GetRowAndColumnErrors(int rowIndex, Hashtable rowErrors, Hashtable colErrors) {
- Debug.Assert(Rows.Count > rowIndex);
- Debug.Assert(rowErrors != null);
- Debug.Assert(colErrors != null);
- DataRow row = Rows[rowIndex];
- if (row.HasErrors) {
- rowErrors.Add(rowIndex, row.RowError);
- DataColumn[] dcArr = row.GetColumnsInError();
- if (dcArr.Length > 0) {
- int[] columnsInError = new int[dcArr.Length];
- string[] columnErrors = new string[dcArr.Length];
- for (int i = 0; i < dcArr.Length; i++) {
- columnsInError[i] = dcArr[i].Ordinal;
- columnErrors[i] = row.GetColumnError(dcArr[i]);
- }
- ArrayList list = new ArrayList();
- list.Add(columnsInError);
- list.Add(columnErrors);
- colErrors.Add(rowIndex, list);
- }
- }
- }
- // Set the row and columns in error..
- private void ConvertToRowError(int rowIndex, Hashtable rowErrors, Hashtable colErrors) {
- Debug.Assert(Rows.Count > rowIndex);
- Debug.Assert(rowErrors != null);
- Debug.Assert(colErrors != null);
- DataRow row = Rows[rowIndex];
- if (rowErrors.ContainsKey(rowIndex)) {
- row.RowError = (string) rowErrors[rowIndex];
- }
- if (colErrors.ContainsKey(rowIndex)) {
- ArrayList list = (ArrayList) colErrors[rowIndex];
- int[] columnsInError = (int[]) list[0];
- string[] columnErrors = (string[]) list[1];
- Debug.Assert(columnsInError.Length == columnErrors.Length);
- for (int i = 0; i < columnsInError.Length; i++) {
- row.SetColumnError(columnsInError[i], columnErrors[i]);
- }
- }
- }
- /// <devdoc>
- /// <para>Indicates whether string comparisons within the table are case-sensitive.</para>
- /// </devdoc>
- [ResDescriptionAttribute(Res.DataTableCaseSensitiveDescr)]
- public bool CaseSensitive {
- get {
- //The following assert is valid except when calling DataSet.set_CaseSensitive which Validates constraints and failing here
- //Debug.Assert(_caseSensitiveUserSet || (null == dataSet) || (dataSet.CaseSensitive == _caseSensitive), "CaseSensitive mismatch");
- return _caseSensitive;
- }
- set {
- if (_caseSensitive != value) {
- bool oldValue = _caseSensitive;
- bool oldUserSet = _caseSensitiveUserSet;
- _caseSensitive = value;
- _caseSensitiveUserSet = true;
- if (DataSet != null && !DataSet.ValidateCaseConstraint()) {
- _caseSensitive = oldValue;
- _caseSensitiveUserSet = oldUserSet;
- throw ExceptionBuilder.CannotChangeCaseLocale();
- }
- SetCaseSensitiveValue(value, true, true);
- }
- _caseSensitiveUserSet = true;
- }
- }
- internal bool AreIndexEventsSuspended {
- get { return (0 < _suspendIndexEvents); }
- }
- internal void RestoreIndexEvents(bool forceReset) {
- Bid.Trace("<ds.DataTable.RestoreIndexEvents|Info> %d#, %d\n", ObjectID, _suspendIndexEvents);
- if (0 < _suspendIndexEvents) {
- _suspendIndexEvents--;
- if (0 == _suspendIndexEvents) {
- Exception first = null;
- SetShadowIndexes();
- try{
- // the length of shadowIndexes will not change
- // but the array instance may change during
- // events during Index.Reset
- int numIndexes = shadowIndexes.Count;
- for (int i = 0; i < numIndexes; i++) {
- Index ndx = shadowIndexes[i];// shadowindexes may change, see ShadowIndexCopy()
- try {
- if (forceReset || ndx.HasRemoteAggregate) {
- ndx.Reset(); // resets & fires
- }
- else {
- ndx.FireResetEvent(); // fire the Reset event we were firing
- }
- }
- catch(Exception e) {
- if (!ADP.IsCatchableExceptionType (e)) {
- throw;
- }
- ExceptionBuilder.TraceExceptionWithoutRethrow(e);
- if (null == first) {
- first = e;
- }
- }
- }
- if (null != first) {
- throw first;
- }
- }
- finally {
- RestoreShadowIndexes();
- }
- }
- }
- }
- internal void SuspendIndexEvents() {
- Bid.Trace("<ds.DataTable.SuspendIndexEvents|Info> %d#, %d\n", ObjectID, _suspendIndexEvents);
- _suspendIndexEvents++;
- }
- [Browsable(false)]
- public bool IsInitialized {
- get {
- return !fInitInProgress;
- }
- }
- private bool IsTypedDataTable {
- get {
- switch (_isTypedDataTable) {
- case 0:
- _isTypedDataTable = (byte)((this.GetType() != typeof(DataTable))? 1 : 2);
- return (1 == _isTypedDataTable);
- case 1:
- return true;
- default:
- return false;
- }
- }
- }
- internal bool SetCaseSensitiveValue(bool isCaseSensitive, bool userSet, bool resetIndexes) {
- if (userSet || (!_caseSensitiveUserSet && (_caseSensitive != isCaseSensitive))) {
- _caseSensitive = isCaseSensitive;
- if (isCaseSensitive) {
- _compareFlags = CompareOptions.None;
- }
- else {
- _compareFlags = CompareOptions.IgnoreCase | CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth;
- }
- if (resetIndexes) {
- ResetIndexes();
- foreach (Constraint constraint in Constraints) {
- constraint.CheckConstraint();
- }
- }
- return true;
- }
- return false;
- }
- private void ResetCaseSensitive() {
- // this method is used design-time scenarios via reflection
- // by the property grid context menu to show the Reset option or not
- SetCaseSensitiveValue((null != dataSet) && dataSet.CaseSensitive, true, true);
- _caseSensitiveUserSet = false;
- }
- internal bool ShouldSerializeCaseSensitive() {
- // this method is used design-time scenarios via reflection
- // by the property grid to show the CaseSensitive property in bold or not
- // by the code dom for persisting the CaseSensitive property or not
- return _caseSensitiveUserSet;
- }
- internal bool SelfNested {
- get {
- // Is this correct? if ((top[i].nestedParentRelation!= null) && (top[i].nestedParentRelation.ParentTable == top[i]))
- foreach(DataRelation rel in ParentRelations) {
- if (rel.Nested && rel.ParentTable == this) {
- return true;
- }
- }
- return false;
- }
- }
- /* internal bool SelfNestedWithOneRelation {
- get {
- return (this.ParentRelations.Count == 1 && (this.ParentRelations[0].ParentTable == this));
- }
- }
- */
- [DebuggerBrowsable(DebuggerBrowsableState.Never)] // don't have debugger view expand this
- internal List<Index> LiveIndexes {
- get {
- if (!AreIndexEventsSuspended) {
- for (int i = indexes.Count-1; 0 <= i; --i) {
- Index index = indexes[i];
- if (index.RefCount <= 1) {
- index.RemoveRef();
- }
- }
- }
- return indexes;
- }
- }
- [
- DefaultValue(SerializationFormat.Xml)
- ]
- public SerializationFormat RemotingFormat {
- get {
- return _remotingFormat;
- }
- set {
- if (value != SerializationFormat.Binary && value != SerializationFormat.Xml) {
- throw ExceptionBuilder.InvalidRemotingFormat(value);
- }
- // table can not have different format than its dataset, unless it is stand alone datatable
- if (this.DataSet != null && value != this.DataSet.RemotingFormat) {
- throw ExceptionBuilder.CanNotSetRemotingFormat();
- }
- _remotingFormat = value;
- }
- }
- // used to keep temporary state of unique Key posiotion to be added for inference only
- internal int UKColumnPositionForInference {
- get {
- return ukColumnPositionForInference;
- }
- set{
- ukColumnPositionForInference= value;
- }
- }
- /// <devdoc>
- /// <para>Gets the collection of child relations for this <see cref='System.Data.DataTable'/>.</para>
- /// </devdoc>
- [
- Browsable(false),
- ResDescriptionAttribute(Res.DataTableChildRelationsDescr),
- DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
- ]
- public DataRelationCollection ChildRelations {
- get {
- if (childRelationsCollection == null)
- childRelationsCollection = new DataRelationCollection.DataTableRelationCollection(this, false);
- return childRelationsCollection;
- }
- }
- /// <devdoc>
- /// <para>Gets the collection of columns that belong to this table.</para>
- /// </devdoc>
- [
- DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
- ResCategoryAttribute(Res.DataCategory_Data),
- ResDescriptionAttribute(Res.DataTableColumnsDescr)
- ]
- public DataColumnCollection Columns {
- get {
- return columnCollection;
- }
- }
- private void ResetColumns() {
- // this method is used design-time scenarios via reflection
- // by the property grid context menu to show the Reset option or not
- Columns.Clear();
- }
- private CompareInfo CompareInfo {
- get {
- if (null == _compareInfo) {
- _compareInfo = Locale.CompareInfo;
- }
- return _compareInfo;
- }
- }
- /// <devdoc>
- /// <para>Gets the collection of constraints maintained by this table.</para>
- /// </devdoc>
- [
- DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
- ResCategoryAttribute(Res.DataCategory_Data),
- ResDescriptionAttribute(Res.DataTableConstraintsDescr)
- ]
- public ConstraintCollection Constraints {
- get {
- return constraintCollection;
- }
- }
- /// <devdoc>
- /// <para>
- /// Resets the <see cref='System.Data.DataTable.Constraints'/> property to its default state.
- /// </para>
- /// </devdoc>
- private void ResetConstraints() {
- Constraints.Clear();
- }
- /// <devdoc>
- /// <para>Gets the <see cref='System.Data.DataSet'/> that this table belongs to.</para>
- /// </devdoc>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Browsable(false), ResDescriptionAttribute(Res.DataTableDataSetDescr)]
- public DataSet DataSet {
- get {
- return dataSet;
- }
- }
- /// <devdoc>
- /// Internal method for setting the DataSet pointer.
- /// </devdoc>
- internal void SetDataSet(DataSet dataSet) {
- if (this.dataSet != dataSet) {
- this.dataSet = dataSet;
- // Inform all the columns of the dataset being set.
- DataColumnCollection cols = Columns;
- for (int i = 0; i < cols.Count; i++)
- cols[i].OnSetDataSet();
- if (this.DataSet != null) {
- defaultView = null;
- }
- //Set the remoting format variable directly
- if (dataSet != null) {
- _remotingFormat = dataSet.RemotingFormat;
- }
- }
- }
- /// <devdoc>
- /// <para>Gets a customized view of the table which may include a
- /// filtered view, or a cursor position.</para>
- /// </devdoc>
- [Browsable(false), ResDescriptionAttribute(Res.DataTableDefaultViewDescr)]
- public DataView DefaultView {
- get {
- DataView view = defaultView;
- if (null == view) {
- if (null != dataSet) {
- view = dataSet.DefaultViewManager.CreateDataView(this);
- }
- else {
- view = new DataView(this, true);
- view.SetIndex2("", DataViewRowState.CurrentRows, null, true);
- }
- // avoid HostProtectionAttribute(Synchronization=true) by not calling virtual methods from inside a lock
- view = Interlocked.CompareExchange<DataView>(ref defaultView, view, null);
- if (null == view) {
- view = defaultView;
- }
- }
- return view;
- }
- }
- /// <devdoc>
- /// <para>Gets or sets the expression that will return a value used to represent
- /// this table in UI.</para>
- /// </devdoc>
- [
- DefaultValue(""),
- ResCategoryAttribute(Res.DataCategory_Data),
- ResDescriptionAttribute(Res.DataTableDisplayExpressionDescr)
- ]
- public string DisplayExpression {
- get {
- return DisplayExpressionInternal;
- }
- set {
- if (value != null && value.Length > 0) {
- this.displayExpression = new DataExpression(this, value);
- }
- else {
- this.displayExpression = null;
- }
- }
- }
- internal string DisplayExpressionInternal {
- get {
- return(displayExpression != null ? displayExpression.Expression : "");
- }
- }
- internal bool EnforceConstraints {
- get {
- if (SuspendEnforceConstraints) {
- return false;
- }
- if (dataSet != null)
- return dataSet.EnforceConstraints;
- return this.enforceConstraints;
- }
- set {
- if (dataSet == null && this.enforceConstraints != value) {
- if (value)
- EnableConstraints();
- this.enforceConstraints = value;
- }
- }
- }
- internal bool SuspendEnforceConstraints {
- get {
- return _suspendEnforceConstraints ;
- }
- set {
- _suspendEnforceConstraints = value;
- }
- }
- internal void EnableConstraints()
- {
- bool errors = false;
- foreach (Constraint constr in Constraints)
- {
- if (constr is UniqueConstraint)
- errors |= constr.IsConstraintViolated();
- }
- foreach (DataColumn column in Columns) {
- if (!column.AllowDBNull) {
- errors |= column.IsNotAllowDBNullViolated();
- }
- if (column.MaxLength >= 0) {
- errors |= column.IsMaxLengthViolated();
- }
- }
- if (errors) {
- this.EnforceConstraints = false;
- throw ExceptionBuilder.EnforceConstraint();
- }
- }
- /// <devdoc>
- /// <para>Gets the collection of customized user information.</para>
- /// </devdoc>
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- Browsable(false),
- ResDescriptionAttribute(Res.ExtendedPropertiesDescr)
- ]
- public PropertyCollection ExtendedProperties {
- get {
- if (extendedProperties == null) {
- extendedProperties = new PropertyCollection();
- }
- return extendedProperties;
- }
- }
- internal IFormatProvider FormatProvider {
- get {
- // used for Formating/Parsing
- // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemglobalizationcultureinfoclassisneutralculturetopic.asp
- if (null == _formatProvider) {
- CultureInfo culture = Locale;
- if (culture.IsNeutralCulture) {
- culture = CultureInfo.InvariantCulture;
- }
- _formatProvider = (IFormatProvider)culture;
- }
- return _formatProvider;
- }
- }
- /// <devdoc>
- /// <para>Gets a value indicating whether there are errors in any of the rows in any of
- /// the tables of the <see cref='System.Data.DataSet'/> to which the table belongs.</para>
- /// </devdoc>
- [Browsable(false), ResDescriptionAttribute(Res.DataTableHasErrorsDescr)]
- public bool HasErrors {
- get {
- for (int i = 0; i < Rows.Count; i++) {
- if (Rows[i].HasErrors) {
- return true;
- }
- }
- return false;
- }
- }
- /// <devdoc>
- /// <para>Gets or sets the locale information used to compare strings within the table.</para>
- /// <para>Also used for locale sensitive, case,kana,width insensitive column name lookups</para>
- /// <para>Also used for converting values to and from string</para>
- /// </devdoc>
- [ResDescriptionAttribute(Res.DataTableLocaleDescr)]
- public CultureInfo Locale {
- get {
- // used for Comparing not Formatting/Parsing
- Debug.Assert(null != _culture, "null culture");
- Debug.Assert(_cultureUserSet || (null == dataSet) || _culture.Equals(dataSet.Locale), "Locale mismatch");
- return _culture;
- }
- set {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.set_Locale|API> %d#\n", ObjectID);
- try {
- bool userSet = true;
- if (null == value) {
- // reset Locale to inherit from DataSet
- userSet = false;
- value = (null != dataSet) ? dataSet.Locale : _culture;
- }
- if (_culture != value && !_culture.Equals(value)) {
- bool flag = false;
- bool exceptionThrown = false;
- CultureInfo oldLocale = _culture;
- bool oldUserSet = _cultureUserSet;
- try {
- _cultureUserSet = true;
- SetLocaleValue(value, true, false);
- if ((null == DataSet) || DataSet.ValidateLocaleConstraint()) {
- flag = false;
- SetLocaleValue(value, true, true);
- flag = true;
- }
- }
- catch {
- exceptionThrown = true;
- throw;
- }
- finally {
- if (!flag) { // reset old locale if ValidationFailed or exception thrown
- try {
- SetLocaleValue(oldLocale, true, true);
- }
- catch(Exception e) { // failed to reset all indexes for all constraints
- if (!Common.ADP.IsCatchableExceptionType(e)) {
- throw;
- }
- Common.ADP.TraceExceptionWithoutRethrow(e);
- }
- _cultureUserSet = oldUserSet;
- if (!exceptionThrown) {
- throw ExceptionBuilder.CannotChangeCaseLocale(null);
- }
- }
- }
- SetLocaleValue(value, true, true);
- }
- _cultureUserSet = userSet;
- }
- finally{
- Bid.ScopeLeave(ref hscp);
- }
- }
- }
- internal bool SetLocaleValue(CultureInfo culture, bool userSet, bool resetIndexes) {
- Debug.Assert(null != culture, "SetLocaleValue: no locale");
- if (userSet || resetIndexes || (!_cultureUserSet && !_culture.Equals(culture))) {
- _culture = culture;
- _compareInfo = null;
- _formatProvider = null;
- _hashCodeProvider = null;
- foreach(DataColumn column in Columns) {
- column._hashCode = GetSpecialHashCode(column.ColumnName);
- }
- if (resetIndexes) {
- ResetIndexes();
- foreach (Constraint constraint in Constraints) {
- constraint.CheckConstraint();
- }
- }
- return true;
- }
- return false;
- }
- internal bool ShouldSerializeLocale() {
- // this method is used design-time scenarios via reflection
- // by the property grid to show the Locale property in bold or not
- // by the code dom for persisting the Locale property or not
- // we always want the locale persisted if set by user or different the current thread if standalone table
- // but that logic should by performed by the serializion code
- return _cultureUserSet;
- }
- /// <devdoc>
- /// <para>Gets or sets the initial starting size for this table.</para>
- /// </devdoc>
- [
- DefaultValue(50),
- ResCategoryAttribute(Res.DataCategory_Data),
- ResDescriptionAttribute(Res.DataTableMinimumCapacityDescr)
- ]
- public int MinimumCapacity {
- get {
- return recordManager.MinimumCapacity;
- }
- set {
- if (value != recordManager.MinimumCapacity) {
- recordManager.MinimumCapacity = value;
- }
- }
- }
- internal int RecordCapacity {
- get {
- return recordManager.RecordCapacity;
- }
- }
- internal int ElementColumnCount {
- get {
- return elementColumnCount;
- }
- set {
- if ((value > 0) && (xmlText != null))
- throw ExceptionBuilder.TableCannotAddToSimpleContent();
- else elementColumnCount = value;
- }
- }
- /// <devdoc>
- /// <para>Gets the collection of parent relations for this <see cref='System.Data.DataTable'/>.</para>
- /// </devdoc>
- [
- Browsable(false),
- ResDescriptionAttribute(Res.DataTableParentRelationsDescr),
- DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
- ]
- public DataRelationCollection ParentRelations {
- get {
- if (parentRelationsCollection == null)
- parentRelationsCollection = new DataRelationCollection.DataTableRelationCollection(this, true);
- return parentRelationsCollection;
- }
- }
- internal bool MergingData {
- get {
- return mergingData;
- }
- set {
- mergingData = value;
- }
- }
- internal DataRelation[] NestedParentRelations {
- get {
- #if DEBUG
- DataRelation[] nRel = FindNestedParentRelations();
- Debug.Assert(nRel.Length == _nestedParentRelations.Length, "nestedParent cache is broken");
- for(int i = 0; i < nRel.Length; i++) {
- Debug.Assert(null != nRel[i], "null relation");
- Debug.Assert(null != _nestedParentRelations[i], "null relation");
- Debug.Assert(nRel[i] == _nestedParentRelations[i], "unequal relations");
- }
- #endif
- return _nestedParentRelations;
- }
- }
- internal bool SchemaLoading {
- get {
- return schemaLoading;
- }
- }
- internal void CacheNestedParent() {
- _nestedParentRelations = FindNestedParentRelations();
- }
- private DataRelation[] FindNestedParentRelations() {
- List<DataRelation> nestedParents = null;
- foreach(DataRelation relation in this.ParentRelations) {
- if(relation.Nested) {
- if (null == nestedParents) {
- nestedParents = new List<DataRelation>();
- }
- nestedParents.Add(relation);
- }
- }
- if ((null == nestedParents) || (nestedParents.Count == 0)) {
- return EmptyArrayDataRelation;
- }
- return nestedParents.ToArray();
- }
- internal int NestedParentsCount {
- get {
- int count = 0;
- foreach(DataRelation relation in this.ParentRelations) {
- if(relation.Nested)
- count++;
- }
- return count;
- }
- }
- /// <devdoc>
- /// <para>Gets or sets an array of columns that function as primary keys for the data
- /// table.</para>
- /// </devdoc>
- [
- TypeConverter(typeof(PrimaryKeyTypeConverter)),
- ResDescriptionAttribute(Res.DataTablePrimaryKeyDescr),
- ResCategoryAttribute(Res.DataCategory_Data),
- Editor("Microsoft.VSDesigner.Data.Design.PrimaryKeyEditor, " + AssemblyRef.MicrosoftVSDesigner, "System.Drawing.Design.UITypeEditor, " + AssemblyRef.SystemDrawing)
- ]
- public DataColumn[] PrimaryKey {
- get {
- UniqueConstraint primayKeyConstraint = primaryKey;
- if (null != primayKeyConstraint) {
- Debug.Assert(2 <= primaryKey.ConstraintIndex.RefCount, "bad primaryKey index RefCount");
- return primayKeyConstraint.Key.ToArray();
- }
- return zeroColumns;
- }
- set {
- UniqueConstraint key = null;
- UniqueConstraint existingKey = null;
- // Loading with persisted property
- if (fInitInProgress && value != null) {
- delayedSetPrimaryKey = value;
- return;
- }
- if ((value != null) && (value.Length != 0)) {
- int count = 0;
- for (int i = 0; i < value.Length; i++) {
- if (value[i] != null)
- count++;
- else
- break;
- }
- if (count != 0) {
- DataColumn[] newValue = value;
- if (count != value.Length) {
- newValue = new DataColumn[count];
- for (int i = 0; i < count; i++)
- newValue[i] = value[i];
- }
- key = new UniqueConstraint(newValue);
- if (key.Table != this)
- throw ExceptionBuilder.TableForeignPrimaryKey();
- }
- }
- if (key == primaryKey || (key != null && key.Equals(primaryKey)))
- return;
- // Use an existing UniqueConstraint that matches if one exists
- if ((existingKey = (UniqueConstraint)Constraints.FindConstraint(key)) != null) {
- key.ColumnsReference.CopyTo(existingKey.Key.ColumnsReference, 0);
- key = existingKey;
- }
- UniqueConstraint oldKey = primaryKey;
- primaryKey = null;
- if (oldKey != null) {
- oldKey.ConstraintIndex.RemoveRef();
- // SQLBU 429176: if PrimaryKey is removed, reset LoadDataRow indexes
- if (null != loadIndex) {
- loadIndex.RemoveRef();
- loadIndex = null;
- }
- if (null != loadIndexwithOriginalAdded) {
- loadIndexwithOriginalAdded.RemoveRef();
- loadIndexwithOriginalAdded = null;
- }
- if (null != loadIndexwithCurrentDeleted) {
- loadIndexwithCurrentDeleted.RemoveRef();
- loadIndexwithCurrentDeleted = null;
- }
- Constraints.Remove(oldKey);
- }
- // Add the key if there isnt an existing matching key in collection
- if (key != null && existingKey == null)
- Constraints.Add(key);
- primaryKey = key;
- Debug.Assert(Constraints.FindConstraint(primaryKey) == primaryKey, "PrimaryKey is not in ConstraintCollection");
- _primaryIndex = (key != null) ? key.Key.GetIndexDesc() : zeroIndexField;
- if (primaryKey != null) {
- // must set index for DataView.Sort before setting AllowDBNull which can fail
- key.ConstraintIndex.AddRef();
- for (int i = 0; i < key.ColumnsReference.Length; i++)
- key.ColumnsReference[i].AllowDBNull = false;
- }
- }
- }
- /// <devdoc>
- /// <para>
- /// Indicates whether the <see cref='System.Data.DataTable.PrimaryKey'/> property should be persisted.
- /// </para>
- /// </devdoc>
- private bool ShouldSerializePrimaryKey() {
- return(primaryKey != null);
- }
- /// <devdoc>
- /// <para>
- /// Resets the <see cref='System.Data.DataTable.PrimaryKey'/> property to its default state.
- /// </para>
- /// </devdoc>
- private void ResetPrimaryKey() {
- PrimaryKey = null;
- }
- /// <devdoc>
- /// <para>Gets the collection of rows that belong to this table.</para>
- /// </devdoc>
- [Browsable(false), ResDescriptionAttribute(Res.DataTableRowsDescr)]
- public DataRowCollection Rows {
- get {
- return rowCollection;
- }
- }
- /// <devdoc>
- /// <para>Gets or sets the name of the table.</para>
- /// </devdoc>
- [
- RefreshProperties(RefreshProperties.All),
- DefaultValue(""),
- ResCategoryAttribute(Res.DataCategory_Data),
- ResDescriptionAttribute(Res.DataTableTableNameDescr)
- ]
- public string TableName {
- get {
- return tableName;
- }
- set {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.set_TableName|API> %d#, value='%ls'\n", ObjectID, value);
- try {
- if (value == null) {
- value = "";
- }
- CultureInfo currentLocale = this.Locale;
- if (String.Compare(tableName, value, true, currentLocale) != 0) {
- if (dataSet != null) {
- if (value.Length == 0)
- throw ExceptionBuilder.NoTableName();
- if ((0 == String.Compare(value, dataSet.DataSetName, true, dataSet.Locale)) && !fNestedInDataset)
- throw ExceptionBuilder.DatasetConflictingName(dataSet.DataSetName);
- DataRelation[] nestedRelations = NestedParentRelations;
- if (nestedRelations.Length == 0) {
- dataSet.Tables.RegisterName(value, this.Namespace);
- }
- else {
- foreach(DataRelation rel in nestedRelations) {
- if (!rel.ParentTable.Columns.CanRegisterName(value)) {
- throw ExceptionBuilder.CannotAddDuplicate2(value);
- }
- }
- // if it cannot register the following line will throw exception
- dataSet.Tables.RegisterName(value, this.Namespace);
- foreach(DataRelation rel in nestedRelations) {
- rel.ParentTable.Columns.RegisterColumnName(value, null);
- rel.ParentTable.Columns.UnregisterName(this.TableName);
- }
- }
- if (tableName.Length != 0) {
- dataSet.Tables.UnregisterName(tableName);
- }
- }
- RaisePropertyChanging("TableName");
- tableName = value;
- encodedTableName = null;
- }
- else if (String.Compare(tableName, value, false, currentLocale) != 0) {
- RaisePropertyChanging("TableName");
- tableName = value;
- encodedTableName = null;
- }
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- }
- internal string EncodedTableName {
- get {
- string encodedTblName = this.encodedTableName;
- if (null == encodedTblName) {
- encodedTblName = XmlConvert.EncodeLocalName( this.TableName );
- this.encodedTableName = encodedTblName;
- }
- return encodedTblName;
- }
- }
- private string GetInheritedNamespace(List<DataTable> visitedTables){
- // if there is nested relation: ie: this table is nested child of a another table and
- // if it is not self nested, return parent tables NS: Meanwhile make sure SQLBUDT 240219 is FIXED
- DataRelation[] nestedRelations = NestedParentRelations;
- if (nestedRelations.Length > 0) {
- for(int i =0; i < nestedRelations.Length; i++) {
- DataRelation rel = nestedRelations[i];
- if (rel.ParentTable.tableNamespace != null) {
- return rel.ParentTable.tableNamespace; // if parent table has a non-null NS, return it
- }
- }
- // Assumption, in hierarchy of multiple nested relation, a child table with no NS, has DataRelation
- // only and only with parent DataTable witin the same namespace
- int j = 0;
- while(j < nestedRelations.Length &&((nestedRelations[j].ParentTable == this)||(visitedTables.Contains(nestedRelations[j].ParentTable)))) {
- j++;
- }
- if (j < nestedRelations.Length) {
- DataTable parentTable = nestedRelations[j].ParentTable;
- if (!visitedTables.Contains(parentTable))
- visitedTables.Add(parentTable);
- return parentTable.GetInheritedNamespace(visitedTables);// this is the same as return parentTable.Namespace
- }
- } // dont put else
- if (DataSet != null) { // if it cant return from parent tables, return NS from dataset, if exists
- return DataSet.Namespace;
- }
- else {
- return string.Empty;
- }
- }
- /// <devdoc>
- /// <para>
- /// Gets or sets the namespace for the <see cref='System.Data.DataTable'/>.
- /// </para>
- /// </devdoc>
- [
- ResCategoryAttribute(Res.DataCategory_Data),
- ResDescriptionAttribute(Res.DataTableNamespaceDescr)
- ]
- public string Namespace {
- get {
- if (tableNamespace == null) {
- return GetInheritedNamespace(new List<DataTable>());
- }
- return tableNamespace;
- }
- set {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.set_Namespace|API> %d#, value='%ls'\n", ObjectID, value);
- try {
- if(value != tableNamespace) {
- if (dataSet != null) {
- string realNamespace = (value == null ? GetInheritedNamespace(new List<DataTable>()) : value);
- if (realNamespace != Namespace) {
- // do this extra check only if the namespace is really going to change
- // inheritance-wise.
- if (dataSet.Tables.Contains( this.TableName, realNamespace, true, true))
- throw ExceptionBuilder.DuplicateTableName2(this.TableName, realNamespace);
- CheckCascadingNamespaceConflict(realNamespace);
- }
- }
- CheckNamespaceValidityForNestedRelations(value);
- DoRaiseNamespaceChange();
- }
- tableNamespace = value;
- }
- finally{
- Bid.ScopeLeave(ref hscp);
- }
- }
- }
- internal bool IsNamespaceInherited() {
- return (null == tableNamespace);
- }
- internal void CheckCascadingNamespaceConflict(string realNamespace){
- foreach (DataRelation rel in ChildRelations)
- if ((rel.Nested) && (rel.ChildTable != this) && (rel.ChildTable.tableNamespace == null)) {
- DataTable childTable = rel.ChildTable;
- if (dataSet.Tables.Contains( childTable.TableName, realNamespace, false, true))
- throw ExceptionBuilder.DuplicateTableName2(this.TableName, realNamespace);
- childTable.CheckCascadingNamespaceConflict(realNamespace);
- }
- }
- internal void CheckNamespaceValidityForNestedRelations(string realNamespace){
- foreach(DataRelation rel in ChildRelations) {
- if (rel.Nested) {
- if (realNamespace != null) {
- rel.ChildTable.CheckNamespaceValidityForNestedParentRelations(realNamespace, this);
- }
- else{
- rel.ChildTable.CheckNamespaceValidityForNestedParentRelations(GetInheritedNamespace(new List<DataTable>()), this);
- }
- }
- }
- if (realNamespace == null) { // this will affect this table if it has parent relations
- this.CheckNamespaceValidityForNestedParentRelations(GetInheritedNamespace(new List<DataTable>()), this);
- }
- }
- internal void CheckNamespaceValidityForNestedParentRelations(string ns, DataTable parentTable) {
- foreach(DataRelation rel in ParentRelations){
- if (rel.Nested) {
- if (rel.ParentTable != parentTable && rel.ParentTable.Namespace != ns) {
- throw ExceptionBuilder.InValidNestedRelation(this.TableName);
- }
- }
- }
- }
- internal void DoRaiseNamespaceChange(){
- RaisePropertyChanging("Namespace");
- // raise column Namespace change
- foreach (DataColumn col in Columns)
- if (col._columnUri == null)
- col.RaisePropertyChanging("Namespace");
- foreach (DataRelation rel in ChildRelations)
- if ((rel.Nested) && (rel.ChildTable != this)) {
- DataTable childTable = rel.ChildTable;
- rel.ChildTable.DoRaiseNamespaceChange();
- }
- }
- /// <devdoc>
- /// <para>
- /// Indicates whether the <see cref='System.Data.DataTable.Namespace'/> property should be persisted.
- /// </para>
- /// </devdoc>
- private bool ShouldSerializeNamespace() {
- return(tableNamespace != null);
- }
- /// <devdoc>
- /// <para>
- /// Resets the <see cref='System.Data.DataTable.Namespace'/> property to its default state.
- /// </para>
- /// </devdoc>
- private void ResetNamespace() {
- this.Namespace = null;
- }
- /// <devdoc>
- /// <para>[To be supplied.]</para>
- /// </devdoc>
- virtual public void BeginInit() {
- fInitInProgress = true;
- }
- /// <devdoc>
- /// <para>[To be supplied.]</para>
- /// </devdoc>
- virtual public void EndInit() {
- if (dataSet == null || !dataSet.fInitInProgress) {
- Columns.FinishInitCollection();
- Constraints.FinishInitConstraints();
- foreach(DataColumn dc in Columns){
- if (dc.Computed) {
- dc.Expression = dc.Expression;
- }
- }
- }
- fInitInProgress = false; // [....] : 77890. It is must that we set off this flag after calling FinishInitxxx();
- if (delayedSetPrimaryKey != null) {
- PrimaryKey = delayedSetPrimaryKey;
- delayedSetPrimaryKey = null;
- }
- if (delayedViews.Count > 0) {
- foreach(DataView dv in delayedViews) {
- dv.EndInit();
- }
- delayedViews.Clear();
- }
- OnInitialized();
- }
- /// <devdoc>
- /// <para>[To be supplied.]</para>
- /// </devdoc>
- [
- DefaultValue(""),
- ResCategoryAttribute(Res.DataCategory_Data),
- ResDescriptionAttribute(Res.DataTablePrefixDescr)
- ]
- public string Prefix {
- get { return tablePrefix;}
- set {
- if (value == null) {
- value = "";
- }
- Bid.Trace("<ds.DataTable.set_Prefix|API> %d#, value='%ls'\n", ObjectID, value);
- if ((XmlConvert.DecodeName(value) == value) &&
- (XmlConvert.EncodeName(value) != value))
- throw ExceptionBuilder.InvalidPrefix(value);
- tablePrefix = value;
- }
- }
- internal DataColumn XmlText {
- get {
- return xmlText;
- }
- set {
- if (xmlText != value) {
- if (xmlText != null) {
- if (value != null) {
- throw ExceptionBuilder.MultipleTextOnlyColumns();
- }
- Columns.Remove(xmlText);
- }
- else {
- Debug.Assert(value != null, "Value shoud not be null ??");
- Debug.Assert(value.ColumnMapping == MappingType.SimpleContent, "should be text node here");
- if (value != Columns[value.ColumnName])
- Columns.Add(value);
- }
- xmlText = value;
- }
- }
- }
- internal decimal MaxOccurs {
- get {
- return maxOccurs;
- }
- set {
- maxOccurs = value;
- }
- }
- internal decimal MinOccurs {
- get {
- return minOccurs;
- }
- set {
- minOccurs = value;
- }
- }
- internal void SetKeyValues(DataKey key, object[] keyValues, int record) {
- for (int i = 0; i < keyValues.Length; i++) {
- key.ColumnsReference[i][record] = keyValues[i];
- }
- }
- internal DataRow FindByIndex(Index ndx, object[] key) {
- Range range = ndx.FindRecords(key);
- if (range.IsNull) {
- return null;
- }
- return this.recordManager[ndx.GetRecord(range.Min)];
- }
- internal DataRow FindMergeTarget(DataRow row, DataKey key, Index ndx) {
- DataRow targetRow = null;
- // Primary key match
- if (key.HasValue) {
- Debug.Assert(ndx != null);
- int findRecord = (row.oldRecord == -1) ? row.newRecord : row.oldRecord;
- object[] values = key.GetKeyValues(findRecord);
- targetRow = FindByIndex(ndx, values);
- }
- return targetRow;
- }
- private void SetMergeRecords(DataRow row, int newRecord, int oldRecord, DataRowAction action) {
- if (newRecord != -1) {
- SetNewRecord(row, newRecord, action, true, true);
- SetOldRecord(row, oldRecord);
- }
- else {
- SetOldRecord(row, oldRecord);
- if (row.newRecord != -1) {
- Debug.Assert(action == DataRowAction.Delete, "Unexpected SetNewRecord action in merge function.");
- SetNewRecord(row, newRecord, action, true, true);
- }
- }
- }
- internal DataRow MergeRow(DataRow row, DataRow targetRow, bool preserveChanges, Index idxSearch) {
- if (targetRow == null) {
- targetRow = this.NewEmptyRow();
- targetRow.oldRecord = recordManager.ImportRecord(row.Table, row.oldRecord);
- targetRow.newRecord = targetRow.oldRecord;
- if(row.oldRecord != row.newRecord) {
- targetRow.newRecord = recordManager.ImportRecord(row.Table, row.newRecord);
- }
- InsertRow(targetRow, -1);
- }
- else {
- // SQLBU 500789: Record Manager corruption during Merge when target row in edit state
- // the newRecord would be freed and overwrite tempRecord (which became the newRecord)
- // this would leave the DataRow referencing a freed record and leaking memory for the now lost record
- int proposedRecord = targetRow.tempRecord; // by saving off the tempRecord, EndEdit won't free newRecord
- targetRow.tempRecord = -1;
- try {
- DataRowState saveRowState = targetRow.RowState;
- int saveIdxRecord = (saveRowState == DataRowState.Added) ? targetRow.newRecord : saveIdxRecord = targetRow.oldRecord;
- int newRecord;
- int oldRecord;
- if (targetRow.RowState == DataRowState.Unchanged && row.RowState == DataRowState.Unchanged) {
- // unchanged row merging with unchanged row
- oldRecord = targetRow.oldRecord;
- newRecord = (preserveChanges) ? recordManager.CopyRecord(this, oldRecord, -1) : targetRow.newRecord;
- oldRecord = recordManager.CopyRecord(row.Table, row.oldRecord, targetRow.oldRecord);
- SetMergeRecords(targetRow, newRecord, oldRecord, DataRowAction.Change);
- }
- else if (row.newRecord == -1) {
- // Incoming row is deleted
- oldRecord = targetRow.oldRecord;
- if (preserveChanges) {
- newRecord = (targetRow.RowState == DataRowState.Unchanged)? recordManager.CopyRecord(this, oldRecord, -1) : targetRow.newRecord;
- }
- else
- newRecord = -1;
- oldRecord = recordManager.CopyRecord(row.Table, row.oldRecord, oldRecord);
- // Change index record, need to update index
- if (saveIdxRecord != ((saveRowState == DataRowState.Added) ? newRecord : oldRecord)) {
- SetMergeRecords(targetRow, newRecord, oldRecord, (newRecord == -1) ? DataRowAction.Delete : DataRowAction.Change);
- idxSearch.Reset();
- saveIdxRecord = ((saveRowState == DataRowState.Added) ? newRecord : oldRecord);
- } else {
- SetMergeRecords(targetRow, newRecord, oldRecord, (newRecord == -1) ? DataRowAction.Delete : DataRowAction.Change);
- }
- }
- else {
- // incoming row is added, modified or unchanged (targetRow is not unchanged)
- oldRecord = targetRow.oldRecord;
- newRecord = targetRow.newRecord;
- if (targetRow.RowState == DataRowState.Unchanged) {
- newRecord = recordManager.CopyRecord(this, oldRecord, -1);
- }
- oldRecord = recordManager.CopyRecord(row.Table, row.oldRecord, oldRecord);
- if (!preserveChanges) {
- newRecord = recordManager.CopyRecord(row.Table, row.newRecord, newRecord);
- }
- SetMergeRecords(targetRow, newRecord, oldRecord, DataRowAction.Change);
- }
- if (saveRowState == DataRowState.Added && targetRow.oldRecord != -1)
- idxSearch.Reset();
- Debug.Assert(saveIdxRecord == ((saveRowState == DataRowState.Added) ? targetRow.newRecord : targetRow.oldRecord), "oops, you change index record without noticing it");
- }
- finally {
- targetRow.tempRecord = proposedRecord;
- }
- }
- // Merge all errors
- if (row.HasErrors) {
- if (targetRow.RowError.Length == 0) {
- targetRow.RowError = row.RowError;
- } else {
- targetRow.RowError += " ]:[ " + row.RowError;
- }
- DataColumn[] cols = row.GetColumnsInError();
- for (int i = 0; i < cols.Length; i++) {
- DataColumn col = targetRow.Table.Columns[cols[i].ColumnName];
- targetRow.SetColumnError(col, row.GetColumnError(cols[i]));
- }
- }else {
- if (!preserveChanges) {
- targetRow.ClearErrors();
- }
- }
- return targetRow;
- }
- /// <devdoc>
- /// <para>Commits all the changes made to this table since the last time <see cref='System.Data.DataTable.AcceptChanges'/> was called.</para>
- /// </devdoc>
- public void AcceptChanges() {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.AcceptChanges|API> %d#\n", ObjectID);
- try {
- DataRow[] oldRows = new DataRow[Rows.Count];
- Rows.CopyTo(oldRows, 0);
- // delay updating of indexes until after all
- // AcceptChange calls have been completed
- SuspendIndexEvents();
- try {
- for (int i = 0; i < oldRows.Length; ++i) {
- if (oldRows[i].rowID != -1) {
- oldRows[i].AcceptChanges();
- }
- }
- }
- finally {
- RestoreIndexEvents(false);
- }
- }
- finally{
- Bid.ScopeLeave(ref hscp);
- }
- }
- // Prevent inlining so that reflection calls are not moved to caller that may be in a different assembly that may have a different grant set.
- [MethodImpl(MethodImplOptions.NoInlining)]
- protected virtual DataTable CreateInstance() {
- return (DataTable) Activator.CreateInstance(this.GetType(), true);
- }
- public virtual DataTable Clone() {
- return Clone(null);
- }
- internal DataTable Clone(DataSet cloneDS) {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.Clone|INFO> %d#, cloneDS=%d\n", ObjectID, (cloneDS != null) ? cloneDS.ObjectID : 0);
- try {
- DataTable clone = CreateInstance();
- if (clone.Columns.Count > 0) // [....] : To clean up all the schema in strong typed dataset.
- clone.Reset();
- return CloneTo(clone, cloneDS, false);
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- private DataTable IncrementalCloneTo (DataTable sourceTable, DataTable targetTable) {
- foreach(DataColumn dc in sourceTable.Columns) {
- if (targetTable.Columns[dc.ColumnName] == null) {
- targetTable.Columns.Add(dc.Clone());
- }
- }
- return targetTable;
- }
- private DataTable CloneHierarchy (DataTable sourceTable, DataSet ds, Hashtable visitedMap) {
- if (visitedMap == null)
- visitedMap = new Hashtable();
- if (visitedMap.Contains(sourceTable))
- return ((DataTable)visitedMap[sourceTable]);
- DataTable destinationTable = ds.Tables[sourceTable.TableName, sourceTable.Namespace];
- if ((destinationTable != null && destinationTable.Columns.Count > 0)) {
- destinationTable = IncrementalCloneTo(sourceTable,destinationTable);
- // get extra columns from source into destination , increamental read
- }
- else {
- if (destinationTable == null) {
- destinationTable = new DataTable();
- // fxcop: new DataTable values for CaseSensitive, Locale, Namespace will come from CloneTo
- ds.Tables.Add(destinationTable);
- }
- destinationTable = sourceTable.CloneTo(destinationTable, ds, true);
- }
- visitedMap[sourceTable] = destinationTable;
- // start cloning relation
- foreach( DataRelation r in sourceTable.ChildRelations ) {
- DataTable childTable = CloneHierarchy((DataTable)r.ChildTable, ds, visitedMap);
- }
- return destinationTable;
- }
- private DataTable CloneTo(DataTable clone, DataSet cloneDS, bool skipExpressionColumns) {
- // we do clone datatables while we do readxmlschema, so we do not want to clone columnexpressions if we call this from ReadXmlSchema
- // it will cause exception to be thrown in cae expression refers to a table that is not in hirerachy or not created yet
- Debug.Assert(clone != null, "The table passed in has to be newly created empty DataTable.");
- // set All properties
- clone.tableName = tableName;
- clone.tableNamespace = tableNamespace;
- clone.tablePrefix = tablePrefix;
- clone.fNestedInDataset = fNestedInDataset;
- clone._culture = _culture;
- clone._cultureUserSet = _cultureUserSet;
- clone._compareInfo = _compareInfo;
- clone._compareFlags = _compareFlags;
- clone._formatProvider = _formatProvider;
- clone._hashCodeProvider = _hashCodeProvider;
- clone._caseSensitive = _caseSensitive;
- clone._caseSensitiveUserSet = _caseSensitiveUserSet;
- clone.displayExpression = displayExpression;
- clone.typeName = typeName; //[....]
- clone.repeatableElement = repeatableElement; //[....]
- clone.MinimumCapacity = MinimumCapacity;
- clone.RemotingFormat = RemotingFormat;
- // clone.SerializeHierarchy = SerializeHierarchy;
- // add all columns
- DataColumnCollection clmns = this.Columns;
- for (int i = 0; i < clmns.Count; i++) {
- clone.Columns.Add(clmns[i].Clone());
- }
- // add all expressions if Clone is invoked only on DataTable otherwise DataSet.Clone will assign expressions after creating all relationships.
- if (!skipExpressionColumns && cloneDS == null) {
- for (int i = 0; i < clmns.Count; i++) {
- clone.Columns[clmns[i].ColumnName].Expression = clmns[i].Expression;
- }
- }
- // Create PrimaryKey
- DataColumn[] pkey = PrimaryKey;
- if (pkey.Length > 0) {
- DataColumn[] key = new DataColumn[pkey.Length];
- for (int i = 0; i < pkey.Length; i++) {
- key[i] = clone.Columns[pkey[i].Ordinal];
- }
- clone.PrimaryKey = key;
- }
- // now clone all unique constraints
- // Rename first
- for (int j = 0; j < Constraints.Count; j++) {
- ForeignKeyConstraint foreign = Constraints[j] as ForeignKeyConstraint;
- UniqueConstraint unique = Constraints[j] as UniqueConstraint;
- if (foreign != null) {
- if (foreign.Table == foreign.RelatedTable) {
- ForeignKeyConstraint clonedConstraint = foreign.Clone(clone);
- Constraint oldConstraint = clone.Constraints.FindConstraint(clonedConstraint);
- if (oldConstraint != null) {
- oldConstraint.ConstraintName = Constraints[j].ConstraintName;
- }
- }
- }
- else if (unique != null) {
- UniqueConstraint clonedConstraint = unique.Clone(clone);
- Constraint oldConstraint = clone.Constraints.FindConstraint(clonedConstraint);
- if (oldConstraint != null) {
- oldConstraint.ConstraintName = Constraints[j].ConstraintName;
- foreach (Object key in clonedConstraint.ExtendedProperties.Keys) {
- oldConstraint.ExtendedProperties[key] = clonedConstraint.ExtendedProperties[key];
- }
- }
- }
- }
- // then add
- for (int j = 0; j < Constraints.Count; j++) {
- if (! clone.Constraints.Contains(Constraints[j].ConstraintName, true)) {
- ForeignKeyConstraint foreign = Constraints[j] as ForeignKeyConstraint;
- UniqueConstraint unique = Constraints[j] as UniqueConstraint;
- if (foreign != null) {
- if (foreign.Table == foreign.RelatedTable) {
- ForeignKeyConstraint newforeign = foreign.Clone(clone);
- if (newforeign != null) { // we cant make sure that we recieve a cloned FKC,since it depends if table and relatedtable be the same
- clone.Constraints.Add(newforeign);
- }
- }
- }
- else if (unique != null) {
- clone.Constraints.Add(unique.Clone(clone));
- }
- }
- }
- // ...Extended Properties...
- if (this.extendedProperties != null) {
- foreach(Object key in this.extendedProperties.Keys) {
- clone.ExtendedProperties[key]=this.extendedProperties[key];
- }
- }
- return clone;
- }
- public DataTable Copy(){
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.Copy|API> %d#\n", ObjectID);
- try {
- DataTable destTable = this.Clone();
- foreach (DataRow row in Rows)
- CopyRow(destTable, row);
- return destTable;
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- /// <devdoc>
- /// <para>Occurs when a value has been submitted for this column.</para>
- /// </devdoc>
- [ResCategoryAttribute(Res.DataCategory_Data), ResDescriptionAttribute(Res.DataTableColumnChangingDescr)]
- public event DataColumnChangeEventHandler ColumnChanging {
- add {
- Bid.Trace("<ds.DataTable.add_ColumnChanging|API> %d#\n", ObjectID);
- onColumnChangingDelegate += value;
- }
- remove {
- Bid.Trace("<ds.DataTable.remove_ColumnChanging|API> %d#\n", ObjectID);
- onColumnChangingDelegate -= value;
- }
- }
- /// <devdoc>
- /// <para>[To be supplied.]</para>
- /// </devdoc>
- [ResCategoryAttribute(Res.DataCategory_Data), ResDescriptionAttribute(Res.DataTableColumnChangedDescr)]
- public event DataColumnChangeEventHandler ColumnChanged {
- add {
- Bid.Trace("<ds.DataTable.add_ColumnChanged|API> %d#\n", ObjectID);
- onColumnChangedDelegate += value;
- }
- remove {
- Bid.Trace("<ds.DataTable.remove_ColumnChanged|API> %d#\n", ObjectID);
- onColumnChangedDelegate -= value;
- }
- }
- [
- ResCategoryAttribute(Res.DataCategory_Action),
- ResDescriptionAttribute(Res.DataSetInitializedDescr)
- ]
- public event System.EventHandler Initialized {
- add {
- onInitialized += value;
- }
- remove {
- onInitialized -= value;
- }
- }
- internal event PropertyChangedEventHandler PropertyChanging {
- add {
- Bid.Trace("<ds.DataTable.add_PropertyChanging|INFO> %d#\n", ObjectID);
- onPropertyChangingDelegate += value;
- }
- remove {
- Bid.Trace("<ds.DataTable.remove_PropertyChanging|INFO> %d#\n", ObjectID);
- onPropertyChangingDelegate -= value;
- }
- }
- /// <devdoc>
- /// <para>
- /// Occurs after a row in the table has been successfully edited.
- /// </para>
- /// </devdoc>
- [ResCategoryAttribute(Res.DataCategory_Data), ResDescriptionAttribute(Res.DataTableRowChangedDescr)]
- public event DataRowChangeEventHandler RowChanged {
- add {
- Bid.Trace("<ds.DataTable.add_RowChanged|API> %d#\n", ObjectID);
- onRowChangedDelegate += value;
- }
- remove {
- Bid.Trace("<ds.DataTable.remove_RowChanged|API> %d#\n", ObjectID);
- onRowChangedDelegate -= value;
- }
- }
- /// <devdoc>
- /// <para>
- /// Occurs when the <see cref='System.Data.DataRow'/> is changing.
- /// </para>
- /// </devdoc>
- [ResCategoryAttribute(Res.DataCategory_Data), ResDescriptionAttribute(Res.DataTableRowChangingDescr)]
- public event DataRowChangeEventHandler RowChanging {
- add {
- Bid.Trace("<ds.DataTable.add_RowChanging|API> %d#\n", ObjectID);
- onRowChangingDelegate += value;
- }
- remove {
- Bid.Trace("<ds.DataTable.remove_RowChanging|API> %d#\n", ObjectID);
- onRowChangingDelegate -= value;
- }
- }
- /// <devdoc>
- /// <para>
- /// Occurs before a row in the table is
- /// about to be deleted.
- /// </para>
- /// </devdoc>
- [ResCategoryAttribute(Res.DataCategory_Data), ResDescriptionAttribute(Res.DataTableRowDeletingDescr)]
- public event DataRowChangeEventHandler RowDeleting {
- add {
- Bid.Trace("<ds.DataTable.add_RowDeleting|API> %d#\n", ObjectID);
- onRowDeletingDelegate += value;
- }
- remove {
- Bid.Trace("<ds.DataTable.remove_RowDeleting|API> %d#\n", ObjectID);
- onRowDeletingDelegate -= value;
- }
- }
- /// <devdoc>
- /// <para>
- /// Occurs after a row in the
- /// table has been deleted.
- /// </para>
- /// </devdoc>
- [ResCategoryAttribute(Res.DataCategory_Data), ResDescriptionAttribute(Res.DataTableRowDeletedDescr)]
- public event DataRowChangeEventHandler RowDeleted {
- add {
- Bid.Trace("<ds.DataTable.add_RowDeleted|API> %d#\n", ObjectID);
- onRowDeletedDelegate += value;
- }
- remove {
- Bid.Trace("<ds.DataTable.remove_RowDeleted|API> %d#\n", ObjectID);
- onRowDeletedDelegate -= value;
- }
- }
- [ResCategoryAttribute(Res.DataCategory_Data), ResDescriptionAttribute(Res.DataTableRowsClearingDescr)]
- public event DataTableClearEventHandler TableClearing {
- add {
- Bid.Trace("<ds.DataTable.add_TableClearing|API> %d#\n", ObjectID);
- onTableClearingDelegate += value;
- }
- remove {
- Bid.Trace("<ds.DataTable.remove_TableClearing|API> %d#\n", ObjectID);
- onTableClearingDelegate -= value;
- }
- }
- [ResCategoryAttribute(Res.DataCategory_Data), ResDescriptionAttribute(Res.DataTableRowsClearedDescr)]
- public event DataTableClearEventHandler TableCleared {
- add {
- Bid.Trace("<ds.DataTable.add_TableCleared|API> %d#\n", ObjectID);
- onTableClearedDelegate += value;
- }
- remove {
- Bid.Trace("<ds.DataTable.remove_TableCleared|API> %d#\n", ObjectID);
- onTableClearedDelegate -= value;
- }
- }
- [ResCategoryAttribute(Res.DataCategory_Data), ResDescriptionAttribute(Res.DataTableRowsNewRowDescr)]
- public event DataTableNewRowEventHandler TableNewRow {
- add {
- onTableNewRowDelegate += value;
- }
- remove {
- onTableNewRowDelegate -= value;
- }
- }
- [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public override ISite Site {
- get {
- return base.Site;
- }
- set {
- ISite oldSite = Site;
- if (value == null && oldSite != null) {
- IContainer cont = oldSite.Container;
- if (cont != null) {
- for (int i = 0; i < Columns.Count; i++) {
- if (Columns[i].Site != null) {
- cont.Remove(Columns[i]);
- }
- }
- }
- }
- base.Site = value;
- }
- }
- internal DataRow AddRecords(int oldRecord, int newRecord) {
- DataRow row;
- if (oldRecord == -1 && newRecord == -1)
- {
- row = NewRow(-1);
- AddRow(row);
- }
- else
- {
- row = NewEmptyRow();
- row.oldRecord = oldRecord;
- row.newRecord = newRecord;
- InsertRow(row, -1);
- }
- return row;
- }
- internal void AddRow(DataRow row) {
- AddRow(row, -1);
- }
- internal void AddRow(DataRow row, int proposedID) {
- InsertRow(row, proposedID, -1);
- }
- internal void InsertRow(DataRow row, int proposedID, int pos) {
- InsertRow(row, proposedID, pos, /*fireEvent*/true);
- }
- internal void InsertRow(DataRow row, long proposedID, int pos, bool fireEvent) {
- Exception deferredException = null;
- if (row == null) {
- throw ExceptionBuilder.ArgumentNull("row");
- }
- if (row.Table != this) {
- throw ExceptionBuilder.RowAlreadyInOtherCollection();
- }
- if (row.rowID != -1) {
- throw ExceptionBuilder.RowAlreadyInTheCollection();
- }
- row.BeginEdit(); // ensure something's there.
- int record = row.tempRecord;
- row.tempRecord = -1;
- if (proposedID == -1) {
- proposedID = this.nextRowID;
- }
- bool rollbackOnException;
- if (rollbackOnException = (nextRowID <= proposedID)) { // WebData 109005
- nextRowID = checked(proposedID + 1);
- }
- try {
- try {
- row.rowID = proposedID;
- // this method may cause DataView.OnListChanged in which another row may be added
- SetNewRecordWorker(row, record, DataRowAction.Add, false, false, pos, fireEvent, out deferredException); // now we do add the row to collection before OnRowChanged (RaiseRowChanged)
- }
- catch {
- if (rollbackOnException && (nextRowID == proposedID+1)) {
- nextRowID = proposedID;
- }
- row.rowID = -1;
- row.tempRecord = record;
- throw;
- }
- // since expression evaluation occurred in SetNewRecordWorker, there may have been a problem that
- // was deferred to this point. If so, throw now since row has already been added.
- if (deferredException != null)
- throw deferredException;
- if (EnforceConstraints && !inLoad ) { // if we are evaluating expression, we need to validate constraints
- int columnCount = columnCollection.Count;
- for (int i = 0; i < columnCount; ++i) {
- DataColumn column = columnCollection[i];
- if (column.Computed) {
- column.CheckColumnConstraint(row, DataRowAction.Add);
- }
- }
- }
- }
- finally {
- row.ResetLastChangedColumn();// if expression is evaluated while adding, before return, we want to clear it
- }
- }
- internal void CheckNotModifying(DataRow row) {
- if (row.tempRecord != -1) {
- row.EndEdit();
- //throw ExceptionBuilder.ModifyingRow();
- }
- }
- /// <devdoc>
- /// <para>
- /// Clears the table of all data.</para>
- /// </devdoc>
- public void Clear() {
- Clear(true);
- }
- internal void Clear(bool clearAll) {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.Clear|INFO> %d#, clearAll=%d{bool}\n", ObjectID, clearAll);
- try {
- Debug.Assert(null == rowDiffId, "wasn't previously cleared");
- rowDiffId = null;
- if (dataSet != null)
- dataSet.OnClearFunctionCalled(this);
- bool shouldFireClearEvents = (this.Rows.Count != 0); // if Rows is already empty, this is noop
- DataTableClearEventArgs e = null;
- if (shouldFireClearEvents) {
- e = new DataTableClearEventArgs (this);
- OnTableClearing(e);
- }
- if (dataSet != null && dataSet.EnforceConstraints) {
- for (ParentForeignKeyConstraintEnumerator constraints = new ParentForeignKeyConstraintEnumerator(dataSet, this); constraints.GetNext();) {
- ForeignKeyConstraint constraint = constraints.GetForeignKeyConstraint();
- constraint.CheckCanClearParentTable(this);
- }
- }
- recordManager.Clear(clearAll);
- // SQLBU 415729: Serious performance issue when calling Clear()
- // this improves performance by iterating over rows instead of computing by index
- foreach(DataRow row in Rows) {
- row.oldRecord = -1;
- row.newRecord = -1;
- row.tempRecord = -1;
- row.rowID = -1;
- row.RBTreeNodeId = 0;
- }
- Rows.ArrayClear();
- ResetIndexes();
- if (shouldFireClearEvents) {
- OnTableCleared(e);
- }
- // SQLBU 501916 - DataTable internal index is corrupted:'5'
- foreach(DataColumn column in Columns) {
- EvaluateDependentExpressions(column);
- }
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- internal void CascadeAll(DataRow row, DataRowAction action) {
- if (DataSet != null && DataSet.fEnableCascading) {
- for (ParentForeignKeyConstraintEnumerator constraints = new ParentForeignKeyConstraintEnumerator(dataSet, this); constraints.GetNext();) {
- constraints.GetForeignKeyConstraint().CheckCascade(row, action);
- }
- }
- }
- internal void CommitRow(DataRow row) {
- // Fire Changing event
- DataRowChangeEventArgs drcevent = OnRowChanging(null, row, DataRowAction.Commit);
- if (!inDataLoad)
- CascadeAll(row, DataRowAction.Commit);
- SetOldRecord(row, row.newRecord);
- OnRowChanged(drcevent, row, DataRowAction.Commit);
- }
- internal int Compare(string s1, string s2) {
- return Compare(s1, s2, null);
- }
- internal int Compare(string s1, string s2, CompareInfo comparer) {
- object obj1 = s1;
- object obj2 = s2;
- if (obj1 == obj2)
- return 0;
- if (obj1 == null)
- return -1;
- if (obj2 == null)
- return 1;
- int leng1 = s1.Length;
- int leng2 = s2.Length;
- for (; leng1 > 0; leng1--) {
- if (s1[leng1-1] != 0x20 && s1[leng1-1] != 0x3000) // 0x3000 is Ideographic Whitespace
- break;
- }
- for (; leng2 > 0; leng2--) {
- if (s2[leng2-1] != 0x20 && s2[leng2-1] != 0x3000)
- break;
- }
- return (comparer ?? this.CompareInfo).Compare(s1, 0, leng1, s2, 0, leng2, _compareFlags);
- }
- internal int IndexOf(string s1, string s2) {
- return CompareInfo.IndexOf(s1, s2, _compareFlags);
- }
- internal bool IsSuffix(string s1, string s2) {
- return CompareInfo.IsSuffix(s1, s2, _compareFlags);
- }
- /// <devdoc>
- /// <para>Computes the given expression on the current rows that pass the filter criteria.</para>
- /// </devdoc>
- public object Compute(string expression, string filter) {
- DataRow[] rows = Select(filter, "", DataViewRowState.CurrentRows);
- DataExpression expr = new DataExpression(this, expression);
- return expr.Evaluate(rows);
- }
- bool System.ComponentModel.IListSource.ContainsListCollection {
- get {
- return false;
- }
- }
- internal void CopyRow(DataTable table, DataRow row)
- {
- int oldRecord = -1, newRecord = -1;
- if (row == null)
- return;
- if (row.oldRecord != -1) {
- oldRecord = table.recordManager.ImportRecord(row.Table, row.oldRecord);
- }
- if (row.newRecord != -1) {
- if (row.newRecord != row.oldRecord) {
- newRecord = table.recordManager.ImportRecord(row.Table, row.newRecord);
- }
- else
- newRecord = oldRecord;
- }
- DataRow targetRow = table.AddRecords(oldRecord, newRecord);
- if (row.HasErrors) {
- targetRow.RowError = row.RowError;
- DataColumn[] cols = row.GetColumnsInError();
- for (int i = 0; i < cols.Length; i++) {
- DataColumn col = targetRow.Table.Columns[cols[i].ColumnName];
- targetRow.SetColumnError(col, row.GetColumnError(cols[i]));
- }
- }
- }
- internal void DeleteRow(DataRow row) {
- if (row.newRecord == -1) {
- throw ExceptionBuilder.RowAlreadyDeleted();
- }
- // Store.PrepareForDelete(row);
- SetNewRecord(row, -1, DataRowAction.Delete, false, true);
- }
- private void CheckPrimaryKey() {
- if (primaryKey == null) throw ExceptionBuilder.TableMissingPrimaryKey();
- }
- internal DataRow FindByPrimaryKey(object[] values) {
- CheckPrimaryKey();
- return FindRow(primaryKey.Key, values);
- }
- internal DataRow FindByPrimaryKey(object value) {
- CheckPrimaryKey();
- return FindRow(primaryKey.Key, value);
- }
- private DataRow FindRow(DataKey key, object[] values) {
- Index index = GetIndex(NewIndexDesc(key));
- Range range = index.FindRecords(values);
- if (range.IsNull)
- return null;
- return recordManager[index.GetRecord(range.Min)];
- }
- private DataRow FindRow(DataKey key, object value) {
- Index index = GetIndex(NewIndexDesc(key));
- Range range = index.FindRecords(value);
- if (range.IsNull)
- return null;
- return recordManager[index.GetRecord(range.Min)];
- }
- internal string FormatSortString(IndexField[] indexDesc) {
- StringBuilder builder = new StringBuilder();
- foreach (IndexField field in indexDesc) {
- if (0 < builder.Length) {
- builder.Append(", ");
- }
- builder.Append(field.Column.ColumnName);
- if (field.IsDescending) {
- builder.Append(" DESC");
- }
- }
- return builder.ToString();
- }
- internal void FreeRecord(ref int record) {
- recordManager.FreeRecord(ref record);
- }
- public DataTable GetChanges() {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.GetChanges|API> %d#\n", ObjectID);
- try {
- DataTable dtChanges = this.Clone();
- DataRow row = null;
- for (int i = 0; i < Rows.Count; i++) {
- row = Rows[i];
- if (row.oldRecord != row.newRecord)
- dtChanges.ImportRow(row);
- }
- if (dtChanges.Rows.Count == 0)
- return null;
- return dtChanges;
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- public DataTable GetChanges(DataRowState rowStates)
- {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.GetChanges|API> %d#, rowStates=%d{ds.DataRowState}\n", ObjectID, (int)rowStates);
- try {
- DataTable dtChanges = this.Clone();
- DataRow row = null;
- // check that rowStates is valid DataRowState
- Debug.Assert(Enum.GetUnderlyingType(typeof(DataRowState)) == typeof(Int32), "Invalid DataRowState type");
- for (int i = 0; i < Rows.Count; i++) {
- row = Rows[i];
- if ((row.RowState & rowStates) != 0)
- dtChanges.ImportRow(row);
- }
- if (dtChanges.Rows.Count == 0)
- return null;
- return dtChanges;
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- /// <devdoc>
- /// <para>Returns an array of <see cref='System.Data.DataRow'/> objects that contain errors.</para>
- /// </devdoc>
- public DataRow[] GetErrors() {
- List<DataRow> errorList = new List<DataRow>();
- for (int i = 0; i < Rows.Count; i++) {
- DataRow row = Rows[i];
- if (row.HasErrors) {
- errorList.Add(row);
- }
- }
- DataRow[] temp = NewRowArray(errorList.Count);
- errorList.CopyTo(temp);
- return temp;
- }
- internal Index GetIndex(IndexField[] indexDesc) {
- return GetIndex(indexDesc, DataViewRowState.CurrentRows, (IFilter)null);
- }
- internal Index GetIndex(string sort, DataViewRowState recordStates, IFilter rowFilter) {
- return GetIndex(ParseSortString(sort), recordStates, rowFilter);
- }
- internal Index GetIndex(IndexField[] indexDesc, DataViewRowState recordStates, IFilter rowFilter) {
- indexesLock.AcquireReaderLock(-1);
- try {
- for (int i = 0; i < indexes.Count; i++) {
- Index index = indexes[i];
- if (index != null) {
- if (index.Equal(indexDesc, recordStates, rowFilter)) {
- return index;
- }
- }
- }
- }
- finally {
- indexesLock.ReleaseReaderLock();
- }
- Index ndx = new Index(this, indexDesc, recordStates, rowFilter);
- ndx.AddRef();
- return ndx;
- }
- IList System.ComponentModel.IListSource.GetList() {
- return DefaultView;
- }
- internal List<DataViewListener> GetListeners() {
- return _dataViewListeners;
- }
- // We need a HashCodeProvider for Case, Kana and Width insensitive
- internal int GetSpecialHashCode(string name) {
- int i;
- for (i = 0; (i < name.Length) && (0x3000 > name[i]); ++i);
- if (name.Length == i) {
- if (null == _hashCodeProvider) {
- // it should use the CaseSensitive property, but V1 shipped this way
- _hashCodeProvider = StringComparer.Create(Locale, true);
- }
- return _hashCodeProvider.GetHashCode(name);
- }
- else {
- return 0;
- }
- }
- public void ImportRow(DataRow row)
- {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.ImportRow|API> %d#\n", ObjectID);
- try {
- int oldRecord = -1, newRecord = -1;
- if (row == null)
- return;
- if (row.oldRecord != -1) {
- oldRecord = recordManager.ImportRecord(row.Table, row.oldRecord);
- }
- if (row.newRecord != -1) { // row not deleted
- if (row.RowState != DataRowState.Unchanged) { // not unchanged, it means Added or modified
- newRecord = recordManager.ImportRecord(row.Table, row.newRecord);
- }
- else
- newRecord = oldRecord;
- }
- if (oldRecord != -1 || newRecord != -1) {
- DataRow targetRow = AddRecords(oldRecord, newRecord);
- if (row.HasErrors) {
- targetRow.RowError = row.RowError;
- DataColumn[] cols = row.GetColumnsInError();
- for (int i = 0; i < cols.Length; i++) {
- DataColumn col = targetRow.Table.Columns[cols[i].ColumnName];
- targetRow.SetColumnError(col, row.GetColumnError(cols[i]));
- }
- }
- }
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- internal void InsertRow(DataRow row, long proposedID) {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.InsertRow|INFO> %d#, row=%d\n", ObjectID, row.ObjectID);
- try {
- if (row.Table != this) {
- throw ExceptionBuilder.RowAlreadyInOtherCollection();
- }
- if (row.rowID != -1) {
- throw ExceptionBuilder.RowAlreadyInTheCollection();
- }
- if (row.oldRecord == -1 && row.newRecord == -1) {
- throw ExceptionBuilder.RowEmpty();
- }
- if (proposedID == -1)
- proposedID = nextRowID;
- row.rowID = proposedID;
- if (nextRowID <= proposedID)
- nextRowID = checked(proposedID + 1);
- DataRowChangeEventArgs drcevent = null;
- if (row.newRecord != -1) {
- row.tempRecord = row.newRecord;
- row.newRecord = -1;
- try {
- drcevent = RaiseRowChanging(null, row, DataRowAction.Add, true);
- }
- catch {
- row.tempRecord = -1;
- throw;
- }
- row.newRecord = row.tempRecord;
- row.tempRecord = -1;
- }
- if (row.oldRecord != -1)
- recordManager[row.oldRecord] = row;
- if (row.newRecord != -1)
- recordManager[row.newRecord] = row;
- Rows.ArrayAdd(row); // SQL BU Defect Tracking 247738, 323482 row should be in the
- // collection when maintaining the indexes
- if (row.RowState == DataRowState.Unchanged){ // how about row.oldRecord == row.newRecord both == -1
- RecordStateChanged(row.oldRecord, DataViewRowState.None, DataViewRowState.Unchanged);
- }
- else {
- RecordStateChanged(row.oldRecord, DataViewRowState.None, row.GetRecordState(row.oldRecord),
- row.newRecord, DataViewRowState.None, row.GetRecordState(row.newRecord));
- }
- if (dependentColumns != null && dependentColumns.Count > 0)
- EvaluateExpressions(row, DataRowAction.Add, null);
- RaiseRowChanged(drcevent, row, DataRowAction.Add);
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- private IndexField [] NewIndexDesc(DataKey key) {
- Debug.Assert(key.HasValue);
- IndexField[] indexDesc = key.GetIndexDesc();
- IndexField[] newIndexDesc = new IndexField[indexDesc.Length];
- Array.Copy(indexDesc, 0, newIndexDesc, 0, indexDesc.Length);
- return newIndexDesc;
- }
- internal int NewRecord() {
- return NewRecord(-1);
- }
- internal int NewUninitializedRecord() {
- return recordManager.NewRecordBase();
- }
- internal int NewRecordFromArray(object[] value) {
- int colCount = columnCollection.Count; // Perf: use the readonly columnCollection field directly
- if (colCount < value.Length) {
- throw ExceptionBuilder.ValueArrayLength();
- }
- int record = recordManager.NewRecordBase();
- try {
- for (int i = 0; i < value.Length; i++) {
- if (null != value[i]) {
- columnCollection[i][record] = value[i];
- }
- else {
- columnCollection[i].Init(record); // Increase AutoIncrementCurrent
- }
- }
- for (int i = value.Length; i < colCount; i++) {
- columnCollection[i].Init(record);
- }
- return record;
- }
- catch (Exception e) {
- //
- if (Common.ADP.IsCatchableOrSecurityExceptionType (e)) {
- FreeRecord(ref record); // WebData 104246
- }
- throw;
- }
- }
- internal int NewRecord(int sourceRecord) {
- int record = recordManager.NewRecordBase();
- int count = columnCollection.Count;
- if (-1 == sourceRecord) {
- for (int i = 0; i < count; ++i) {
- columnCollection[i].Init(record);
- }
- }
- else {
- for (int i = 0; i < count; ++i) {
- columnCollection[i].Copy(sourceRecord, record);
- }
- }
- return record;
- }
- internal DataRow NewEmptyRow() {
- rowBuilder._record = -1;
- DataRow dr = NewRowFromBuilder( rowBuilder );
- if (dataSet != null) {
- DataSet.OnDataRowCreated( dr );
- }
- return dr;
- }
- private DataRow NewUninitializedRow() {
- DataRow dr = NewRow(NewUninitializedRecord());
- return dr;
- }
- /// <devdoc>
- /// <para>Creates a new <see cref='System.Data.DataRow'/>
- /// with the same schema as the table.</para>
- /// </devdoc>
- public DataRow NewRow() {
- DataRow dr = NewRow(-1);
- NewRowCreated(dr); // this is the only API we want this event to be fired
- return dr;
- }
- // Only initialize DataRelation mapping columns (approximately hidden columns)
- internal DataRow CreateEmptyRow() {
- DataRow row = this.NewUninitializedRow();
- foreach( DataColumn c in this.Columns ) {
- if (!XmlToDatasetMap.IsMappedColumn(c)) {
- if (!c.AutoIncrement) {
- if (c.AllowDBNull) {
- row[c] = DBNull.Value;
- }
- else if(c.DefaultValue!=null){
- row[c] = c.DefaultValue;
- }
- }
- else {
- c.Init(row.tempRecord);
- }
- }
- }
- return row;
- }
- private void NewRowCreated(DataRow row) {
- if (null != onTableNewRowDelegate) {
- DataTableNewRowEventArgs eventArg = new DataTableNewRowEventArgs(row);
- OnTableNewRow(eventArg);
- }
- }
- internal DataRow NewRow(int record) {
- if (-1 == record) {
- record = NewRecord(-1);
- }
- rowBuilder._record = record;
- DataRow row = NewRowFromBuilder( rowBuilder );
- recordManager[record] = row;
- if (dataSet != null)
- DataSet.OnDataRowCreated( row );
- return row;
- }
- // This is what a subclassed dataSet overrides to create a new row.
- protected virtual DataRow NewRowFromBuilder(DataRowBuilder builder) {
- return new DataRow(builder);
- }
- /// <devdoc>
- /// <para>Gets the row type.</para>
- /// </devdoc>
- protected virtual Type GetRowType() {
- return typeof(DataRow);
- }
- // Prevent inlining so that reflection calls are not moved to caller that may be in a different assembly that may have a different grant set.
- [MethodImpl(MethodImplOptions.NoInlining)]
- protected internal DataRow[] NewRowArray(int size) {
- if (IsTypedDataTable) {
- if (0 == size) {
- if (null == EmptyDataRowArray) {
- EmptyDataRowArray = (DataRow[]) Array.CreateInstance(GetRowType(), 0);
- }
- return EmptyDataRowArray;
- }
- return (DataRow[]) Array.CreateInstance(GetRowType(), size);
- }
- else {
- return ((0 == size) ? DataTable.zeroRows : new DataRow[size]);
- }
- }
- internal bool NeedColumnChangeEvents {
- get {
- return (IsTypedDataTable || (null != onColumnChangingDelegate) || (null != onColumnChangedDelegate));
- }
- }
- protected internal virtual void OnColumnChanging(DataColumnChangeEventArgs e) {
- // intentionally allow exceptions to bubble up. We haven't committed anything yet.
- Debug.Assert(e != null, "e should not be null");
- if (onColumnChangingDelegate != null) {
- Bid.Trace("<ds.DataTable.OnColumnChanging|INFO> %d#\n", ObjectID);
- onColumnChangingDelegate(this, e);
- }
- }
- protected internal virtual void OnColumnChanged(DataColumnChangeEventArgs e) {
- Debug.Assert(e != null, "e should not be null");
- if (onColumnChangedDelegate != null) {
- Bid.Trace("<ds.DataTable.OnColumnChanged|INFO> %d#\n", ObjectID);
- onColumnChangedDelegate(this, e);
- }
- }
- protected virtual void OnPropertyChanging(PropertyChangedEventArgs pcevent) {
- if (onPropertyChangingDelegate != null) {
- Bid.Trace("<ds.DataTable.OnPropertyChanging|INFO> %d#\n", ObjectID);
- onPropertyChangingDelegate(this, pcevent);
- }
- }
- internal void OnRemoveColumnInternal(DataColumn column) {
- OnRemoveColumn(column);
- }
- /// <devdoc>
- /// <para>Notifies the <see cref='System.Data.DataTable'/> that a <see cref='System.Data.DataColumn'/> is
- /// being removed.</para>
- /// </devdoc>
- protected virtual void OnRemoveColumn(DataColumn column) {
- }
- private DataRowChangeEventArgs OnRowChanged(DataRowChangeEventArgs args, DataRow eRow, DataRowAction eAction) {
- if ((null != onRowChangedDelegate) || IsTypedDataTable) {
- if (null == args) {
- args = new DataRowChangeEventArgs(eRow, eAction);
- }
- OnRowChanged(args);
- }
- return args;
- }
- private DataRowChangeEventArgs OnRowChanging(DataRowChangeEventArgs args, DataRow eRow, DataRowAction eAction) {
- if ((null != onRowChangingDelegate) || IsTypedDataTable) {
- if (null == args) {
- args = new DataRowChangeEventArgs(eRow, eAction);
- }
- OnRowChanging(args);
- }
- return args;
- }
- /// <devdoc>
- /// <para>
- /// Raises the <see cref='System.Data.DataTable.RowChanged'/> event.
- /// </para>
- /// </devdoc>
- protected virtual void OnRowChanged(DataRowChangeEventArgs e) {
- Debug.Assert((null != e) && ((null != onRowChangedDelegate) || IsTypedDataTable), "OnRowChanged arguments");
- if (onRowChangedDelegate != null) {
- Bid.Trace("<ds.DataTable.OnRowChanged|INFO> %d#\n", ObjectID);
- onRowChangedDelegate(this, e);
- }
- }
- /// <devdoc>
- /// <para>
- /// Raises the <see cref='System.Data.DataTable.RowChanging'/> event.
- /// </para>
- /// </devdoc>
- protected virtual void OnRowChanging(DataRowChangeEventArgs e) {
- Debug.Assert((null != e) && ((null != onRowChangingDelegate) || IsTypedDataTable), "OnRowChanging arguments");
- if (onRowChangingDelegate != null) {
- Bid.Trace("<ds.DataTable.OnRowChanging|INFO> %d#\n", ObjectID);
- onRowChangingDelegate(this, e);
- }
- }
- /// <devdoc>
- /// <para>
- /// Raises the <see cref='System.Data.DataTable.OnRowDeleting'/> event.
- /// </para>
- /// </devdoc>
- protected virtual void OnRowDeleting(DataRowChangeEventArgs e) {
- Debug.Assert((null != e) && ((null != onRowDeletingDelegate) || IsTypedDataTable), "OnRowDeleting arguments");
- if (onRowDeletingDelegate != null) {
- Bid.Trace("<ds.DataTable.OnRowDeleting|INFO> %d#\n", ObjectID);
- onRowDeletingDelegate(this, e);
- }
- }
- /// <devdoc>
- /// <para>
- /// Raises the <see cref='System.Data.DataTable.OnRowDeleted'/> event.
- /// </para>
- /// </devdoc>
- protected virtual void OnRowDeleted(DataRowChangeEventArgs e) {
- Debug.Assert((null != e) && ((null != onRowDeletedDelegate) || IsTypedDataTable), "OnRowDeleted arguments");
- if (onRowDeletedDelegate != null) {
- Bid.Trace("<ds.DataTable.OnRowDeleted|INFO> %d#\n", ObjectID);
- onRowDeletedDelegate(this, e);
- }
- }
- protected virtual void OnTableCleared(DataTableClearEventArgs e) {
- if (onTableClearedDelegate != null) {
- Bid.Trace("<ds.DataTable.OnTableCleared|INFO> %d#\n", ObjectID);
- onTableClearedDelegate(this, e);
- }
- }
- protected virtual void OnTableClearing(DataTableClearEventArgs e) {
- if (onTableClearingDelegate != null) {
- Bid.Trace("<ds.DataTable.OnTableClearing|INFO> %d#\n", ObjectID);
- onTableClearingDelegate(this, e);
- }
- }
- protected virtual void OnTableNewRow(DataTableNewRowEventArgs e) {
- if (onTableNewRowDelegate != null) {
- Bid.Trace("<ds.DataTable.OnTableNewRow|INFO> %d#\n", ObjectID);
- onTableNewRowDelegate(this, e);
- }
- }
- private void OnInitialized() {
- if (onInitialized != null) {
- Bid.Trace("<ds.DataTable.OnInitialized|INFO> %d#\n", ObjectID);
- onInitialized(this, EventArgs.Empty);
- }
- }
- internal IndexField[] ParseSortString(string sortString) {
- IndexField[] indexDesc = zeroIndexField;
- if ((null != sortString) && (0 < sortString.Length)) {
- string[] split = sortString.Split(new char[] { ','});
- indexDesc = new IndexField[split.Length];
- for (int i = 0; i < split.Length; i++) {
- string current = split[i].Trim();
- // handle ASC and DESC.
- int length = current.Length;
- bool descending = false;
- if (length >= 5 && String.Compare(current, length - 4, " ASC", 0, 4, StringComparison.OrdinalIgnoreCase) == 0) {
- current = current.Substring(0, length - 4).Trim();
- }
- else if (length >= 6 && String.Compare(current, length - 5, " DESC", 0, 5, StringComparison.OrdinalIgnoreCase) == 0) {
- descending = true;
- current = current.Substring(0, length - 5).Trim();
- }
- // handle brackets.
- if (current.StartsWith("[", StringComparison.Ordinal)) {
- if (current.EndsWith("]", StringComparison.Ordinal)) {
- current = current.Substring(1, current.Length - 2);
- }
- else {
- throw ExceptionBuilder.InvalidSortString(split[i]);
- }
- }
- // find the column.
- DataColumn column = Columns[current];
- if(column == null) {
- throw ExceptionBuilder.ColumnOutOfRange(current);
- }
- indexDesc[i] = new IndexField(column, descending);
- }
- }
- return indexDesc;
- }
- internal void RaisePropertyChanging(string name) {
- OnPropertyChanging(new PropertyChangedEventArgs(name));
- }
- // Notify all indexes that record changed.
- // Only called when Error was changed.
- internal void RecordChanged(int record) {
- Debug.Assert (record != -1, "Record number must be given");
- SetShadowIndexes(); // how about new assert?
- try {
- int numIndexes = shadowIndexes.Count;
- for (int i = 0; i < numIndexes; i++) {
- Index ndx = shadowIndexes[i];// shadowindexes may change, see ShadowIndexCopy()
- if (0 < ndx.RefCount) {
- ndx.RecordChanged(record);
- }
- }
- }
- finally{
- RestoreShadowIndexes();
- }
- }
- // for each index in liveindexes invok RecordChanged
- // oldIndex and newIndex keeps position of record before delete and after insert in each index in order
- // LiveIndexes[n-m] will have its information in oldIndex[n-m] and newIndex[n-m]
- internal void RecordChanged(int[] oldIndex, int[] newIndex) {
- SetShadowIndexes();
- Debug.Assert (oldIndex.Length == newIndex.Length, "Size oldIndexes and newIndexes should be the same");
- Debug.Assert (oldIndex.Length == shadowIndexes.Count, "Size of OldIndexes should be the same as size of Live indexes");
- try{
- int numIndexes = shadowIndexes.Count;
- for (int i = 0; i < numIndexes; i++) {
- Index ndx = shadowIndexes[i];// shadowindexes may change, see ShadowIndexCopy()
- if (0 < ndx.RefCount) {
- ndx.RecordChanged(oldIndex[i], newIndex[i]);
- }
- }
- }
- finally{
- RestoreShadowIndexes();
- }
- }
- internal void RecordStateChanged(int record, DataViewRowState oldState, DataViewRowState newState) {
- SetShadowIndexes();
- try{
- int numIndexes = shadowIndexes.Count;
- for (int i = 0; i < numIndexes; i++) {
- Index ndx = shadowIndexes[i];// shadowindexes may change, see ShadowIndexCopy()
- if (0 < ndx.RefCount) {
- ndx.RecordStateChanged(record, oldState, newState);
- }
- }
- }
- finally{
- RestoreShadowIndexes();
- }
- // System.Data.XML.Store.Store.OnROMChanged(record, oldState, newState);
- }
- internal void RecordStateChanged(int record1, DataViewRowState oldState1, DataViewRowState newState1,
- int record2, DataViewRowState oldState2, DataViewRowState newState2) {
- SetShadowIndexes();
- try{
- int numIndexes = shadowIndexes.Count;
- for (int i = 0; i < numIndexes; i++) {
- Index ndx = shadowIndexes[i];// shadowindexes may change, see ShadowIndexCopy()
- if (0 < ndx.RefCount) {
- if (record1 != -1 && record2 != -1)
- ndx.RecordStateChanged(record1, oldState1, newState1,
- record2, oldState2, newState2);
- else if (record1 != -1)
- ndx.RecordStateChanged(record1, oldState1, newState1);
- else if (record2 != -1)
- ndx.RecordStateChanged(record2, oldState2, newState2);
- }
- }
- }
- finally {
- RestoreShadowIndexes();
- }
- // System.Data.XML.Store.Store.OnROMChanged(record1, oldState1, newState1, record2, oldState2, newState2);
- }
- // RemoveRecordFromIndexes removes the given record (using row and version) from all indexes and it stores and returns the position of deleted
- // record from each index
- // IT SHOULD NOT CAUSE ANY EVENT TO BE FIRED
- internal int[] RemoveRecordFromIndexes(DataRow row, DataRowVersion version) {
- int indexCount = LiveIndexes.Count;
- int [] positionIndexes = new int[indexCount];
- int recordNo = row.GetRecordFromVersion(version);
- DataViewRowState states = row.GetRecordState(recordNo);
- while (--indexCount >= 0) {
- if (row.HasVersion(version) && ((states & indexes[indexCount].RecordStates) != DataViewRowState.None)) {
- int index = indexes[indexCount].GetIndex(recordNo);
- if (index > -1) {
- positionIndexes [indexCount] = index;
- indexes[indexCount].DeleteRecordFromIndex(index); // this will delete the record from index and MUSt not fire event
- }
- else {
- positionIndexes [indexCount] = -1; // this means record was not in index
- }
- }
- else {
- positionIndexes [indexCount] = -1; // this means record was not in index
- }
- }
- return positionIndexes;
- }
- // InsertRecordToIndexes inserts the given record (using row and version) to all indexes and it stores and returns the position of inserted
- // record to each index
- // IT SHOULD NOT CAUSE ANY EVENT TO BE FIRED
- internal int[] InsertRecordToIndexes(DataRow row, DataRowVersion version) {
- int indexCount = LiveIndexes.Count;
- int [] positionIndexes = new int[indexCount];
- int recordNo = row.GetRecordFromVersion(version);
- DataViewRowState states = row.GetRecordState(recordNo);
- while (--indexCount >= 0) {
- if (row.HasVersion(version)) {
- if ((states & indexes[indexCount].RecordStates) != DataViewRowState.None) {
- positionIndexes [indexCount] = indexes[indexCount].InsertRecordToIndex(recordNo);
- }
- else {
- positionIndexes [indexCount] = -1;
- }
- }
- }
- return positionIndexes;
- }
- internal void SilentlySetValue(DataRow dr, DataColumn dc, DataRowVersion version, object newValue) {
- // get record for version
- int record = dr.GetRecordFromVersion(version);
- bool equalValues = false;
- if (DataStorage.IsTypeCustomType(dc.DataType) && newValue != dc[record]) {
- // if UDT storage, need to check if reference changed. See bug 385182
- equalValues = false;
- }
- else {
- equalValues = dc.CompareValueTo(record, newValue, true);
- }
- // if expression has changed
- if (!equalValues) {
- int[] oldIndex = dr.Table.RemoveRecordFromIndexes(dr, version);// conditional, if it exists it will try to remove with no event fired
- dc.SetValue(record, newValue);
- int[] newIndex = dr.Table.InsertRecordToIndexes(dr, version);// conditional, it will insert if it qualifies, no event will be fired
- if (dr.HasVersion(version)) {
- if (version != DataRowVersion.Original) {
- dr.Table.RecordChanged(oldIndex, newIndex);
- }
- if (dc.dependentColumns != null) {
- //BugBug - passing in null for cachedRows. This means expression columns as keys does not work when key changes.
- dc.Table.EvaluateDependentExpressions(dc.dependentColumns, dr, version, null);
- }
- }
- }
- dr.ResetLastChangedColumn();
- }
- /// <devdoc>
- /// <para>Rolls back all changes that have been made to the table
- /// since it was loaded, or the last time <see cref='System.Data.DataTable.AcceptChanges'/> was called.</para>
- /// </devdoc>
- public void RejectChanges() {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.RejectChanges|API> %d#\n", ObjectID);
- try{
- DataRow[] oldRows = new DataRow[Rows.Count];
- Rows.CopyTo(oldRows, 0);
- for (int i = 0; i < oldRows.Length; i++) {
- RollbackRow(oldRows[i]);
- }
- }
- finally{
- Bid.ScopeLeave(ref hscp);
- }
- }
- internal void RemoveRow(DataRow row, bool check) {
- if (row.rowID == -1) {
- throw ExceptionBuilder.RowAlreadyRemoved();
- }
- if (check && dataSet != null) {
- for (ParentForeignKeyConstraintEnumerator constraints = new ParentForeignKeyConstraintEnumerator(dataSet, this); constraints.GetNext();) {
- constraints.GetForeignKeyConstraint().CheckCanRemoveParentRow(row);
- }
- }
- int oldRecord = row.oldRecord;
- int newRecord = row.newRecord;
- DataViewRowState oldRecordStatePre = row.GetRecordState(oldRecord);
- DataViewRowState newRecordStatePre = row.GetRecordState(newRecord);
- row.oldRecord = -1;
- row.newRecord = -1;
- if (oldRecord == newRecord) {
- oldRecord = -1;
- }
- RecordStateChanged(oldRecord, oldRecordStatePre, DataViewRowState.None,
- newRecord, newRecordStatePre, DataViewRowState.None);
- FreeRecord(ref oldRecord);
- FreeRecord(ref newRecord);
- row.rowID = -1;
- Rows.ArrayRemove(row);
- }
- // Resets the table back to its original state.
- public virtual void Reset() {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.Reset|API> %d#\n", ObjectID);
- try {
- Clear();
- ResetConstraints();
- DataRelationCollection dr = this.ParentRelations;
- int count = dr.Count;
- while (count > 0) {
- count--;
- dr.RemoveAt(count);
- }
- dr = this.ChildRelations;
- count = dr.Count;
- while (count > 0) {
- count--;
- dr.RemoveAt(count);
- }
- Columns.Clear();
- indexes.Clear();
- }
- finally{
- Bid.ScopeLeave(ref hscp);
- }
- }
- internal void ResetIndexes() {
- ResetInternalIndexes(null);
- }
- internal void ResetInternalIndexes(DataColumn column) {
- Debug.Assert(null != indexes, "unexpected null indexes");
- SetShadowIndexes();
- try{
- // the length of shadowIndexes will not change
- // but the array instance may change during
- // events during Index.Reset
- int numIndexes = shadowIndexes.Count;
- for (int i = 0; i < numIndexes; i++) {
- Index ndx = shadowIndexes[i];// shadowindexes may change, see ShadowIndexCopy()
- if (0 < ndx.RefCount) {
- if (null == column) {
- ndx.Reset();
- }
- else {
- // SQLBU 501916: DataTable internal index is corrupted:'5'
- bool found = false;
- foreach(IndexField field in ndx.IndexFields) {
- if (Object.ReferenceEquals(column, field.Column)) {
- found = true;
- break;
-
- }
- }
- if (found) {
- ndx.Reset();
- }
- }
- }
- }
- }
- finally {
- RestoreShadowIndexes();
- }
- }
- internal void RollbackRow(DataRow row) {
- row.CancelEdit();
- SetNewRecord(row, row.oldRecord, DataRowAction.Rollback, false, true);
- }
- private DataRowChangeEventArgs RaiseRowChanged(DataRowChangeEventArgs args, DataRow eRow, DataRowAction eAction) {
- try {
- if (UpdatingCurrent(eRow, eAction) && (IsTypedDataTable || (null != onRowChangedDelegate))) {
- args = OnRowChanged(args, eRow, eAction);
- }
- // check if we deleting good row
- else if (DataRowAction.Delete == eAction && eRow.newRecord == -1 && (IsTypedDataTable || (null != onRowDeletedDelegate))) {
- if (null == args) {
- args = new DataRowChangeEventArgs(eRow, eAction);
- }
- OnRowDeleted(args);
- }
- }
- catch (Exception f) {
- //
- if (!Common.ADP.IsCatchableExceptionType(f)) {
- throw;
- }
- ExceptionBuilder.TraceExceptionWithoutRethrow(f);
- // ignore the exception
- }
- return args;
- }
- private DataRowChangeEventArgs RaiseRowChanging(DataRowChangeEventArgs args, DataRow eRow, DataRowAction eAction) {
- if (UpdatingCurrent(eRow, eAction) && (IsTypedDataTable || (null != onRowChangingDelegate))) {
- eRow.inChangingEvent = true;
- // don't catch
- try {
- args = OnRowChanging(args, eRow, eAction);
- }
- finally {
- eRow.inChangingEvent = false;
- }
- }
- // check if we deleting good row
- else if (DataRowAction.Delete == eAction && eRow.newRecord != -1 && (IsTypedDataTable || (null != onRowDeletingDelegate))) {
- eRow.inDeletingEvent = true;
- // don't catch
- try {
- if (null == args) {
- args = new DataRowChangeEventArgs(eRow, eAction);
- }
- OnRowDeleting(args);
- }
- finally {
- eRow.inDeletingEvent = false;
- }
- }
- return args;
- }
- private DataRowChangeEventArgs RaiseRowChanging(DataRowChangeEventArgs args, DataRow eRow, DataRowAction eAction, bool fireEvent) {
- // check all constraints
- if (EnforceConstraints && !inLoad ) {
- int columnCount = columnCollection.Count;
- for(int i = 0; i < columnCount; ++i) {
- DataColumn column = columnCollection[i];
- if (!column.Computed || eAction != DataRowAction.Add) {
- column.CheckColumnConstraint(eRow, eAction);
- }
- }
- int constraintCount = constraintCollection.Count;
- for(int i = 0; i < constraintCount; ++i) {
- constraintCollection[i].CheckConstraint(eRow, eAction);
- }
- }
- // $$anandra. Check this event out. May be an issue.
- if (fireEvent) {
- args = RaiseRowChanging(args, eRow, eAction);
- }
- if (!inDataLoad) {
- // cascade things...
- if (!MergingData && eAction != DataRowAction.Nothing && eAction != DataRowAction.ChangeOriginal) {
- CascadeAll(eRow, eAction);
- }
- }
- return args;
- }
- /// <devdoc>
- /// <para>Returns an array of all <see cref='System.Data.DataRow'/> objects.</para>
- /// </devdoc>
- public DataRow[] Select() {
- Bid.Trace("<ds.DataTable.Select|API> %d#\n", ObjectID);
- return new Select(this, "", "", DataViewRowState.CurrentRows).SelectRows();
- }
- /// <devdoc>
- /// <para>Returns an array of all <see cref='System.Data.DataRow'/> objects that match the filter criteria in order of
- /// primary key (or lacking one, order of addition.)</para>
- /// </devdoc>
- public DataRow[] Select(string filterExpression) {
- Bid.Trace("<ds.DataTable.Select|API> %d#, filterExpression='%ls'\n", ObjectID, filterExpression);
- return new Select(this, filterExpression, "", DataViewRowState.CurrentRows).SelectRows();
- }
- /// <devdoc>
- /// <para>Returns an array of all <see cref='System.Data.DataRow'/> objects that match the filter criteria, in the the
- /// specified sort order.</para>
- /// </devdoc>
- public DataRow[] Select(string filterExpression, string sort) {
- Bid.Trace("<ds.DataTable.Select|API> %d#, filterExpression='%ls', sort='%ls'\n", ObjectID, filterExpression, sort);
- return new Select(this, filterExpression, sort, DataViewRowState.CurrentRows).SelectRows();
- }
- /// <devdoc>
- /// <para>Returns an array of all <see cref='System.Data.DataRow'/> objects that match the filter in the order of the
- /// sort, that match the specified state.</para>
- /// </devdoc>
- public DataRow[] Select(string filterExpression, string sort, DataViewRowState recordStates) {
- Bid.Trace("<ds.DataTable.Select|API> %d#, filterExpression='%ls', sort='%ls', recordStates=%d{ds.DataViewRowState}\n", ObjectID, filterExpression, sort, (int)recordStates);
- return new Select(this, filterExpression, sort, recordStates).SelectRows();
- }
- internal void SetNewRecord(DataRow row, int proposedRecord, DataRowAction action = DataRowAction.Change, bool isInMerge = false, bool fireEvent = true, bool suppressEnsurePropertyChanged = false) {
- Exception deferredException = null;
- SetNewRecordWorker(row, proposedRecord, action, isInMerge, suppressEnsurePropertyChanged, -1, fireEvent, out deferredException); // we are going to call below overload from insert
- if (deferredException != null) {
- throw deferredException;
- }
- }
- private void SetNewRecordWorker(DataRow row, int proposedRecord, DataRowAction action, bool isInMerge, bool suppressEnsurePropertyChanged,
- int position, bool fireEvent, out Exception deferredException) {
- // this is the event workhorse... it will throw the changing/changed events
- // and update the indexes. Used by change, add, delete, revert.
- // order of execution is as follows
- //
- // 1) set temp record
- // 2) Check constraints for non-expression columns
- // 3) Raise RowChanging/RowDeleting with temp record
- // 4) set the new record in storage
- // 5) Update indexes with recordStateChanges - this will fire ListChanged & PropertyChanged events on associated views
- // 6) Evaluate all Expressions (exceptions are deferred)- this will fire ListChanged & PropertyChanged events on associated views
- // 7) Raise RowChanged/ RowDeleted
- // 8) Check constraints for expression columns
- Debug.Assert(row != null, "Row can't be null.");
- deferredException = null;
-
- if (row.tempRecord != proposedRecord) {
- // $HACK: for performance reasons, EndUpdate calls SetNewRecord with tempRecord == proposedRecord
- if (!inDataLoad) {
- row.CheckInTable();
- CheckNotModifying(row);
- }
- if (proposedRecord == row.newRecord) {
- if (isInMerge) {
- Debug.Assert(fireEvent, "SetNewRecord is called with wrong parameter");
- RaiseRowChanged(null, row, action);
- }
- return;
- }
- Debug.Assert(!row.inChangingEvent, "How can this row be in an infinite loop?");
- row.tempRecord = proposedRecord;
- }
- DataRowChangeEventArgs drcevent = null;
- try {
- row._action = action;
- drcevent = RaiseRowChanging(null, row, action, fireEvent);
- }
- catch {
- row.tempRecord = -1;
- throw;
- }
- finally {
- row._action = DataRowAction.Nothing;
- }
- row.tempRecord = -1;
- int currentRecord = row.newRecord;
- // if we're deleting, then the oldRecord value will change, so need to track that if it's distinct from the newRecord.
- int secondRecord = (proposedRecord != -1 ?
- proposedRecord :
- (row.RowState != DataRowState.Unchanged ?
- row.oldRecord :
- -1));
- if (action == DataRowAction.Add) { //if we come here from insert we do insert the row to collection
- if (position == -1)
- Rows.ArrayAdd(row);
- else
- Rows.ArrayInsert(row, position);
- }
- List<DataRow> cachedRows = null;
- if ((action == DataRowAction.Delete || action == DataRowAction.Change)
- && dependentColumns != null && dependentColumns.Count > 0) {
- // if there are expression columns, need to cache related rows for deletes and updates (key changes)
- // before indexes are modified.
- cachedRows = new List<DataRow>();
- for (int j = 0; j < ParentRelations.Count; j++) {
- DataRelation relation = ParentRelations[j];
- if (relation.ChildTable != row.Table) {
- continue;
- }
- cachedRows.InsertRange(cachedRows.Count, row.GetParentRows(relation));
- }
- for (int j = 0; j < ChildRelations.Count; j++) {
- DataRelation relation = ChildRelations[j];
- if (relation.ParentTable != row.Table) {
- continue;
- }
- cachedRows.InsertRange(cachedRows.Count, row.GetChildRows(relation));
- }
- }
- // Dev10 Bug 688779: DataRowView.PropertyChanged are not raised on RejectChanges
- // if the newRecord is changing, the propertychanged event should be allowed to triggered for ListChangedType.Changed or .Moved
- // unless the specific condition is known that no data has changed, like DataRow.SetModified()
- if (!suppressEnsurePropertyChanged && !row.HasPropertyChanged && (row.newRecord != proposedRecord)
- && (-1 != proposedRecord) // explictly not fixing Dev10 Bug 692044: DataRowView.PropertyChanged are not raised on DataTable.Delete when mixing current and original records in RowStateFilter
- && (-1 != row.newRecord)) // explictly not fixing parts of Dev10 Bug 697909: when mixing current and original records in RowStateFilter
- {
- // DataRow will believe multiple edits occured and
- // DataView.ListChanged event w/ ListChangedType.ItemChanged will raise DataRowView.PropertyChanged event and
- // PropertyChangedEventArgs.PropertyName will now be empty string so
- // WPF will refresh the entire row
- row.LastChangedColumn = null;
- row.LastChangedColumn = null;
- }
- // Check whether we need to update indexes
- if (LiveIndexes.Count != 0) {
- // Dev10 bug #463087: DataTable internal index is currupted: '5'
- if ((-1 == currentRecord) && (-1 != proposedRecord) && (-1 != row.oldRecord) && (proposedRecord != row.oldRecord)) {
- // the transition from DataRowState.Deleted -> DataRowState.Modified
- // with same orginal record but new current record
- // needs to raise an ItemChanged or ItemMoved instead of ItemAdded in the ListChanged event.
- // for indexes/views listening for both DataViewRowState.Deleted | DataViewRowState.ModifiedCurrent
- currentRecord = row.oldRecord;
- }
- DataViewRowState currentRecordStatePre = row.GetRecordState(currentRecord);
- DataViewRowState secondRecordStatePre = row.GetRecordState(secondRecord);
- row.newRecord = proposedRecord;
- if (proposedRecord != -1)
- this.recordManager[proposedRecord] = row;
- DataViewRowState currentRecordStatePost = row.GetRecordState(currentRecord);
- DataViewRowState secondRecordStatePost = row.GetRecordState(secondRecord);
- // may raise DataView.ListChanged event
- RecordStateChanged(currentRecord, currentRecordStatePre, currentRecordStatePost,
- secondRecord, secondRecordStatePre, secondRecordStatePost);
- }
- else {
- row.newRecord = proposedRecord;
- if (proposedRecord != -1)
- this.recordManager[proposedRecord] = row;
- }
- // Dev10 Bug 461199 - reset the last changed column here, after all
- // DataViews have raised their DataRowView.PropertyChanged event
- row.ResetLastChangedColumn();
- // SQLBU 278737: Record manager corruption when reentrant write operations
- // free the 'currentRecord' only after all the indexes have been updated.
- // Corruption! { if (currentRecord != row.oldRecord) { FreeRecord(ref currentRecord); } }
- // RecordStateChanged raises ListChanged event at which time user may do work
- if (-1 != currentRecord) {
- if (currentRecord != row.oldRecord)
- {
- if ((currentRecord != row.tempRecord) && // Delete, AcceptChanges, BeginEdit
- (currentRecord != row.newRecord) && // RejectChanges & SetAdded
- (row == recordManager[currentRecord])) // AcceptChanges, NewRow
- {
- FreeRecord(ref currentRecord);
- }
- }
- }
- if (row.RowState == DataRowState.Detached && row.rowID != -1) {
- RemoveRow(row, false);
- }
- if (dependentColumns != null && dependentColumns.Count > 0) {
- try {
- EvaluateExpressions(row, action, cachedRows);
- }
- catch (Exception exc) {
- // For DataRows being added, throwing of exception from expression evaluation is
- // deferred until after the row has been completely added.
- if (action != DataRowAction.Add) {
- throw exc;
- }
- else {
- deferredException = exc;
- }
- }
- }
- try {
- if (fireEvent) {
- RaiseRowChanged(drcevent, row, action);
- }
- }
- catch (Exception e) {
- //
- if (!Common.ADP.IsCatchableExceptionType(e)) {
- throw;
- }
- ExceptionBuilder.TraceExceptionWithoutRethrow(e);
- // ignore the exception
- }
- }
- // this is the event workhorse... it will throw the changing/changed events
- // and update the indexes.
- internal void SetOldRecord(DataRow row, int proposedRecord) {
- if (!inDataLoad) {
- row.CheckInTable();
- CheckNotModifying(row);
- }
- if (proposedRecord == row.oldRecord) {
- return;
- }
- int originalRecord = row.oldRecord; // cache old record after potential RowChanging event
- try {
- // Check whether we need to update indexes
- if (LiveIndexes.Count != 0) {
- // Dev10 bug #463087: DataTable internal index is currupted: '5'
- if ((-1 == originalRecord) && (-1 != proposedRecord) && (-1 != row.newRecord) && (proposedRecord != row.newRecord)) {
- // the transition from DataRowState.Added -> DataRowState.Modified
- // with same current record but new original record
- // needs to raise an ItemChanged or ItemMoved instead of ItemAdded in the ListChanged event.
- // for indexes/views listening for both DataViewRowState.Added | DataViewRowState.ModifiedOriginal
- originalRecord = row.newRecord;
- }
- DataViewRowState originalRecordStatePre = row.GetRecordState(originalRecord);
- DataViewRowState proposedRecordStatePre = row.GetRecordState(proposedRecord);
- row.oldRecord = proposedRecord;
- if (proposedRecord != -1)
- this.recordManager[proposedRecord] = row;
- DataViewRowState originalRecordStatePost = row.GetRecordState(originalRecord);
- DataViewRowState proposedRecordStatePost = row.GetRecordState(proposedRecord);
- RecordStateChanged(originalRecord, originalRecordStatePre, originalRecordStatePost,
- proposedRecord, proposedRecordStatePre, proposedRecordStatePost);
- }
- else {
- row.oldRecord = proposedRecord;
- if (proposedRecord != -1)
- this.recordManager[proposedRecord] = row;
- }
- }
- finally {
- if ((originalRecord != -1) && (originalRecord != row.tempRecord) &&
- (originalRecord != row.oldRecord) && (originalRecord != row.newRecord)) {
- FreeRecord(ref originalRecord);
- }
- // else during an event 'row.AcceptChanges(); row.BeginEdit(); row.EndEdit();'
- if (row.RowState == DataRowState.Detached && row.rowID != -1) {
- RemoveRow(row, false);
- }
- }
- }
- private void RestoreShadowIndexes() {
- Debug.Assert(1 <= shadowCount, "unexpected negative shadow count");
- shadowCount--;
- if (0 == shadowCount) {
- shadowIndexes = null;
- }
- }
- private void SetShadowIndexes() {
- if (null == shadowIndexes) {
- Debug.Assert(0 == shadowCount, "unexpected count");
- shadowIndexes = LiveIndexes;
- shadowCount = 1;
- }
- else {
- Debug.Assert(1 <= shadowCount, "unexpected negative shadow count");
- shadowCount++;
- }
- }
- internal void ShadowIndexCopy(){
- if (shadowIndexes == indexes) {
- Debug.Assert(0 < indexes.Count, "unexpected");
- shadowIndexes = new List<Index>(indexes);
- }
- }
- /// <devdoc>
- /// <para>Returns the <see cref='System.Data.DataTable.TableName'/> and <see cref='System.Data.DataTable.DisplayExpression'/>, if there is one as a concatenated string.</para>
- /// </devdoc>
- public override string ToString() {
- if (this.displayExpression == null)
- return this.TableName;
- else
- return this.TableName + " + " + this.DisplayExpressionInternal;
- }
- /// <devdoc>
- /// <para>[To be supplied.]</para>
- /// </devdoc>
- public void BeginLoadData() {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.BeginLoadData|API> %d#\n", ObjectID);
- try {
- if (inDataLoad)
- return;
- inDataLoad = true;
- Debug.Assert(null == loadIndex, "loadIndex should already be null");
- loadIndex = null;
- // LoadDataRow may have been called before BeginLoadData and already
- // initialized loadIndexwithOriginalAdded & loadIndexwithCurrentDeleted
- initialLoad = (Rows.Count == 0);
- if(initialLoad) {
- SuspendIndexEvents();
- } else {
- if (primaryKey != null) {
- loadIndex = primaryKey.Key.GetSortIndex(DataViewRowState.OriginalRows);
- }
- if(loadIndex != null) {
- loadIndex.AddRef();
- }
- }
- if (DataSet != null) {
- savedEnforceConstraints = DataSet.EnforceConstraints;
- DataSet.EnforceConstraints = false;
- }
- else {
- this.EnforceConstraints = false;
- }
- }
- finally{
- Bid.ScopeLeave(ref hscp);
- }
- }
- /// <devdoc>
- /// <para>[To be supplied.]</para>
- /// </devdoc>
- public void EndLoadData() {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.EndLoadData|API> %d#\n", ObjectID);
- try {
- if (!inDataLoad)
- return;
- if(loadIndex != null) {
- loadIndex.RemoveRef();
- }
- if (loadIndexwithOriginalAdded != null) {
- loadIndexwithOriginalAdded.RemoveRef();
- }
- if (loadIndexwithCurrentDeleted != null) {
- loadIndexwithCurrentDeleted.RemoveRef();
- }
- loadIndex = null;
- loadIndexwithOriginalAdded = null;
- loadIndexwithCurrentDeleted = null;
- inDataLoad = false;
- RestoreIndexEvents(false);
- if (DataSet != null)
- DataSet.EnforceConstraints = savedEnforceConstraints;
- else
- this.EnforceConstraints = true;
- }
- finally{
- Bid.ScopeLeave(ref hscp);
- }
- }
- /// <devdoc>
- /// <para>Finds and updates a specific row. If no matching
- /// row is found, a new row is created using the given values.</para>
- /// </devdoc>
- public DataRow LoadDataRow(object[] values, bool fAcceptChanges) {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.LoadDataRow|API> %d#, fAcceptChanges=%d{bool}\n", ObjectID, fAcceptChanges);
- try {
- DataRow row;
- if (inDataLoad) {
- int record = NewRecordFromArray(values);
- if (loadIndex != null) {
- // not expecting LiveIndexes to clear the index we use between calls to LoadDataRow
- Debug.Assert(2 <= loadIndex.RefCount, "bad loadIndex.RefCount");
- int result = loadIndex.FindRecord(record);
- if (result != -1) {
- int resultRecord = loadIndex.GetRecord(result);
- row = recordManager[resultRecord];
- Debug.Assert (row != null, "Row can't be null for index record");
- row.CancelEdit();
- if (row.RowState == DataRowState.Deleted)
- SetNewRecord(row, row.oldRecord, DataRowAction.Rollback, false, true);
- SetNewRecord(row, record, DataRowAction.Change, false, true);
- if (fAcceptChanges)
- row.AcceptChanges();
- return row;
- }
- }
- row = NewRow(record);
- AddRow(row);
- if (fAcceptChanges)
- row.AcceptChanges();
- return row;
- }
- else {
- // In case, BeginDataLoad is not called yet
- row = UpdatingAdd(values);
- if (fAcceptChanges)
- row.AcceptChanges();
- return row;
- }
- }
- finally{
- Bid.ScopeLeave(ref hscp);
- }
- }
- /// <devdoc>
- /// <para>Finds and updates a specific row. If no matching
- /// row is found, a new row is created using the given values.</para>
- /// </devdoc>
- public DataRow LoadDataRow(object[] values, LoadOption loadOption) {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.LoadDataRow|API> %d#, loadOption=%d{ds.LoadOption}\n", ObjectID, (int)loadOption);
- try {
- Index indextoUse = null;
- if (this.primaryKey != null) {
- if (loadOption == LoadOption.Upsert) { // CurrentVersion, and Deleted
- if (loadIndexwithCurrentDeleted == null) {
- loadIndexwithCurrentDeleted = this.primaryKey.Key.GetSortIndex(DataViewRowState.CurrentRows |DataViewRowState.Deleted);
- Debug.Assert(loadIndexwithCurrentDeleted != null, "loadIndexwithCurrentDeleted should not be null" );
- if (loadIndexwithCurrentDeleted != null) {
- loadIndexwithCurrentDeleted.AddRef();
- }
- }
- indextoUse = loadIndexwithCurrentDeleted;
- }
- else {// CurrentVersion, and Deleted : OverwriteRow, PreserveCurrentValues
- if (loadIndexwithOriginalAdded == null) {
- loadIndexwithOriginalAdded = this.primaryKey.Key.GetSortIndex(DataViewRowState.OriginalRows |DataViewRowState.Added);
- Debug.Assert(loadIndexwithOriginalAdded != null, "loadIndexwithOriginalAdded should not be null");
- if (loadIndexwithOriginalAdded != null) {
- loadIndexwithOriginalAdded.AddRef();
- }
- }
- indextoUse = loadIndexwithOriginalAdded;
- }
- // not expecting LiveIndexes to clear the index we use between calls to LoadDataRow
- Debug.Assert(2 <= indextoUse.RefCount, "bad indextoUse.RefCount");
- }
- if(inDataLoad && !AreIndexEventsSuspended) { // we do not want to fire any listchanged in new Load/Fill
- SuspendIndexEvents();// so suspend events here(not suspended == table already has some rows initially)
- }
- DataRow dataRow = LoadRow(values, loadOption, indextoUse);// if indextoUse == null, it means we dont have PK,
- // so LoadRow will take care of just adding the row to end
- return dataRow;
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- internal DataRow UpdatingAdd(object[] values) {
- Index index = null;
- if (this.primaryKey != null) {
- index = this.primaryKey.Key.GetSortIndex(DataViewRowState.OriginalRows);
- }
- if (index != null) {
- int record = NewRecordFromArray(values);
- int result = index.FindRecord(record);
- if (result != -1) {
- int resultRecord = index.GetRecord(result);
- DataRow row = this.recordManager[resultRecord];
- Debug.Assert (row != null, "Row can't be null for index record");
- row.RejectChanges();
- this.SetNewRecord(row, record);
- return row;
- }
- DataRow row2 = NewRow(record);
- Rows.Add(row2);
- return row2;
- }
- return Rows.Add(values);
- }
- internal bool UpdatingCurrent(DataRow row, DataRowAction action) {
- return(action == DataRowAction.Add || action == DataRowAction.Change ||
- action == DataRowAction.Rollback || action == DataRowAction.ChangeOriginal ||
- action == DataRowAction.ChangeCurrentAndOriginal);
- // (action == DataRowAction.Rollback && row.tempRecord != -1));
- }
- internal DataColumn AddUniqueKey(int position) {
- if (_colUnique != null)
- return _colUnique;
- // check to see if we can use already existant PrimaryKey
- DataColumn[] pkey = PrimaryKey;
- if (pkey.Length == 1)
- // We have one-column primary key, so we can use it in our heirarchical relation
- return pkey[0];
- // add Unique, but not primaryKey to the table
- string keyName = XMLSchema.GenUniqueColumnName(TableName + "_Id", this);
- DataColumn key = new DataColumn(keyName, typeof(Int32), null, MappingType.Hidden);
- key.Prefix = tablePrefix;
- key.AutoIncrement = true;
- key.AllowDBNull = false;
- key.Unique = true;
- if (position == -1)
- Columns.Add(key);
- else { // we do have a problem and Imy idea is it is bug. Ask Enzo while Code review. Why we do not set ordinal when we call AddAt?
- for(int i = Columns.Count -1; i >= position; i--) {
- this.Columns[i].SetOrdinalInternal(i+1);
- }
- Columns.AddAt(position, key);
- key.SetOrdinalInternal(position);
- }
- if (pkey.Length == 0)
- PrimaryKey = new DataColumn[] {
- key
- };
- _colUnique = key;
- return _colUnique;
- }
- internal DataColumn AddUniqueKey() {
- return AddUniqueKey(-1);
- }
- internal DataColumn AddForeignKey(DataColumn parentKey) {
- Debug.Assert(parentKey != null, "AddForeignKey: Invalid paramter.. related primary key is null");
- string keyName = XMLSchema.GenUniqueColumnName(parentKey.ColumnName, this);
- DataColumn foreignKey = new DataColumn(keyName, parentKey.DataType, null, MappingType.Hidden);
- Columns.Add(foreignKey);
- return foreignKey;
- }
- internal void UpdatePropertyDescriptorCollectionCache() {
- propertyDescriptorCollectionCache = null;
- }
- /// <devdoc>
- /// Retrieves an array of properties that the given component instance
- /// provides. This may differ from the set of properties the class
- /// provides. If the component is sited, the site may add or remove
- /// additional properties. The returned array of properties will be
- /// filtered by the given set of attributes.
- /// </devdoc>
- internal PropertyDescriptorCollection GetPropertyDescriptorCollection(Attribute[] attributes) {
- if (propertyDescriptorCollectionCache == null) {
- int columnsCount = Columns.Count;
- int relationsCount = ChildRelations.Count;
- PropertyDescriptor[] props = new PropertyDescriptor[columnsCount + relationsCount]; {
- for (int i = 0; i < columnsCount; i++) {
- props[i] = new DataColumnPropertyDescriptor(Columns[i]);
- }
- for (int i = 0; i < relationsCount; i++) {
- props[columnsCount + i] = new DataRelationPropertyDescriptor(ChildRelations[i]);
- }
- }
- propertyDescriptorCollectionCache = new PropertyDescriptorCollection(props);
- }
- return propertyDescriptorCollectionCache;
- }
- internal XmlQualifiedName TypeName {
- get {
- return ((typeName == null) ? XmlQualifiedName.Empty : (XmlQualifiedName)typeName);
- }
- set {
- typeName = value;
- }
- }
- public void Merge(DataTable table)
- {
- Merge(table, false, MissingSchemaAction.Add);
- }
- public void Merge(DataTable table, bool preserveChanges)
- {
- Merge(table, preserveChanges, MissingSchemaAction.Add);
- }
- public void Merge(DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)
- {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.Merge|API> %d#, table=%d, preserveChanges=%d{bool}, missingSchemaAction=%d{ds.MissingSchemaAction}\n", ObjectID, (table != null) ? table.ObjectID : 0, preserveChanges, (int)missingSchemaAction);
- try{
- if (table == null)
- throw ExceptionBuilder.ArgumentNull("table");
- switch(missingSchemaAction) { // @perfnote: Enum.IsDefined
- case MissingSchemaAction.Add:
- case MissingSchemaAction.Ignore:
- case MissingSchemaAction.Error:
- case MissingSchemaAction.AddWithKey:
- Merger merger = new Merger(this, preserveChanges, missingSchemaAction);
- merger.MergeTable(table);
- break;
- default:
- throw Common.ADP.InvalidMissingSchemaAction(missingSchemaAction);
- }
- }
- finally{
- Bid.ScopeLeave(ref hscp);
- }
- }
- public void Load (IDataReader reader){
- Load(reader, LoadOption.PreserveChanges, null);
- }
- public void Load (IDataReader reader, LoadOption loadOption) {
- Load(reader, loadOption, null);
- }
- public virtual void Load (IDataReader reader, LoadOption loadOption, FillErrorEventHandler errorHandler){
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.Load|API> %d#, loadOption=%d{ds.LoadOption}\n", ObjectID, (int)loadOption);
- try {
- if (this.PrimaryKey.Length == 0) {
- DataTableReader dtReader = reader as DataTableReader;
- if (dtReader != null && dtReader.CurrentDataTable == this)
- return; // if not return, it will go to infinite loop
- }
- Common.LoadAdapter adapter = new Common.LoadAdapter();
- adapter.FillLoadOption = loadOption;
- adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
- if (null != errorHandler) {
- adapter.FillError += errorHandler;
- }
- adapter.FillFromReader(new DataTable[] { this }, reader, 0, 0);
- if (!reader.IsClosed && !reader.NextResult()) { //
- reader.Close();
- }
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- private DataRow LoadRow(object[] values, LoadOption loadOption, Index searchIndex) {
- int recordNo;
- DataRow dataRow = null;
- if (searchIndex != null) {
- int[] primaryKeyIndex = new int[0];
- if (this.primaryKey != null) { // I do check above for PK, but in case if someone else gives me some index unrelated to PK
- primaryKeyIndex = new int[this.primaryKey.ColumnsReference.Length];
- for(int i = 0; i < this.primaryKey.ColumnsReference.Length; i++) {
- primaryKeyIndex[i] = this.primaryKey.ColumnsReference[i].Ordinal;
- }
- }
- object[] keys = new object[primaryKeyIndex.Length];
- for(int i = 0; i < primaryKeyIndex.Length; i++) {
- keys[i] = values[primaryKeyIndex[i]];
- }
- Range result = searchIndex.FindRecords(keys);
- if (!result.IsNull) {
- int deletedRowUpsertCount = 0;
- for(int i = result.Min; i <= result.Max; i++) {
- int resultRecord = searchIndex.GetRecord(i);
- dataRow = this.recordManager[resultRecord];
- recordNo = NewRecordFromArray(values);
- //SQLBU DT 33648
- // values array is being reused by DataAdapter, do not modify the values array
- for(int count = 0; count < values.Length; count++) {
- if (null == values[count]) {
- columnCollection[count].Copy(resultRecord, recordNo);
- }
- }
- for(int count = values.Length; count < columnCollection.Count ; count++) {
- columnCollection[count].Copy(resultRecord, recordNo); // if there are missing values
- }
- if (loadOption != LoadOption.Upsert || dataRow.RowState != DataRowState.Deleted) {
- SetDataRowWithLoadOption(dataRow , recordNo, loadOption, true);
- }
- else {
- deletedRowUpsertCount++;
- }
- }
- if (0 == deletedRowUpsertCount) {
- return dataRow;
- }
- }
- }
- recordNo = NewRecordFromArray(values);
- dataRow = NewRow(recordNo);
- // fire rowChanging event here
- DataRowAction action;
- DataRowChangeEventArgs drcevent = null;
- switch(loadOption) {
- case LoadOption.OverwriteChanges:
- case LoadOption.PreserveChanges:
- action = DataRowAction.ChangeCurrentAndOriginal;
- break;
- case LoadOption.Upsert:
- action = DataRowAction.Add;
- break;
- default:
- throw ExceptionBuilder.ArgumentOutOfRange("LoadOption");
- }
- drcevent = RaiseRowChanging(null, dataRow, action);
- this.InsertRow (dataRow, -1, -1, false);
- switch(loadOption) {
- case LoadOption.OverwriteChanges:
- case LoadOption.PreserveChanges:
- this.SetOldRecord(dataRow, recordNo);
- break;
- case LoadOption.Upsert:
- break;
- default:
- throw ExceptionBuilder.ArgumentOutOfRange("LoadOption");
- }
- RaiseRowChanged(drcevent, dataRow, action);
- return dataRow;
- }
- private void SetDataRowWithLoadOption (DataRow dataRow, int recordNo, LoadOption loadOption, bool checkReadOnly) {
- bool hasError = false;
- if (checkReadOnly) {
- foreach(DataColumn dc in this.Columns) {
- if (dc.ReadOnly && !dc.Computed) {
- switch(loadOption) {
- case LoadOption.OverwriteChanges:
- if ((dataRow[dc, DataRowVersion.Current] != dc[recordNo]) ||(dataRow[dc, DataRowVersion.Original] != dc[recordNo]))
- hasError = true;
- break;
- case LoadOption.Upsert:
- if (dataRow[dc, DataRowVersion.Current] != dc[recordNo])
- hasError = true;
- break;
- case LoadOption.PreserveChanges:
- if (dataRow[dc, DataRowVersion.Original] != dc[recordNo])
- hasError = true;
- break;
- }
- }
- }
- } // No Event should be fired in SenNewRecord and SetOldRecord
- // fire rowChanging event here
- DataRowChangeEventArgs drcevent = null;
- DataRowAction action = DataRowAction.Nothing;
- int cacheTempRecord = dataRow.tempRecord;
- dataRow.tempRecord = recordNo;
- switch(loadOption) {
- case LoadOption.OverwriteChanges:
- action = DataRowAction.ChangeCurrentAndOriginal;
- break;
- case LoadOption.Upsert:
- switch(dataRow.RowState) {
- case DataRowState.Unchanged:
- // let see if the incomming value has the same values as existing row, so compare records
- foreach(DataColumn dc in dataRow.Table.Columns) {
- if (0 != dc.Compare(dataRow.newRecord, recordNo)) {
- action = DataRowAction.Change;
- break;
- }
- }
- break;
- case DataRowState.Deleted:
- Debug.Assert(false, "LoadOption.Upsert with deleted row, should not be here");
- break;
- default :
- action = DataRowAction.Change;
- break;
- }
- break;
- case LoadOption.PreserveChanges:
- switch(dataRow.RowState) {
- case DataRowState.Unchanged:
- action = DataRowAction.ChangeCurrentAndOriginal;
- break;
- default:
- action = DataRowAction.ChangeOriginal;
- break;
- }
- break;
- default:
- throw ExceptionBuilder.ArgumentOutOfRange("LoadOption");
- }
- try {
- drcevent = RaiseRowChanging(null, dataRow, action);
- if (action == DataRowAction.Nothing) { // RaiseRowChanging does not fire for DataRowAction.Nothing
- dataRow.inChangingEvent = true;
- try {
- drcevent = OnRowChanging(drcevent, dataRow, action);
- }
- finally {
- dataRow.inChangingEvent = false;
- }
- }
- }
- finally {
- Debug.Assert(dataRow.tempRecord == recordNo, "tempRecord has been changed in event handler");
- if (DataRowState.Detached == dataRow.RowState) {
- // 'row.Table.Remove(row);'
- if (-1 != cacheTempRecord) {
- FreeRecord(ref cacheTempRecord);
- }
- }
- else {
- if (dataRow.tempRecord != recordNo) {
- // 'row.EndEdit(); row.BeginEdit(); '
- if (-1 != cacheTempRecord) {
- FreeRecord(ref cacheTempRecord);
- }
- if (-1 != recordNo) {
- FreeRecord(ref recordNo);
- }
- recordNo = dataRow.tempRecord;
- }
- else {
- dataRow.tempRecord = cacheTempRecord;
- }
- }
- }
- if (dataRow.tempRecord != -1) {
- dataRow.CancelEdit();
- }
- switch(loadOption) {
- case LoadOption.OverwriteChanges:
- this.SetNewRecord(dataRow, recordNo, DataRowAction.Change, false, false);
- this.SetOldRecord(dataRow, recordNo);
- break;
- case LoadOption.Upsert:
- if (dataRow.RowState == DataRowState.Unchanged) {
- this.SetNewRecord(dataRow, recordNo, DataRowAction.Change, false, false);
- if (!dataRow.HasChanges()) {
- this.SetOldRecord(dataRow, recordNo);
- }
- }
- else {
- if (dataRow.RowState == DataRowState.Deleted)
- dataRow.RejectChanges();
- this.SetNewRecord(dataRow, recordNo, DataRowAction.Change, false, false);
- }
- break;
- case LoadOption.PreserveChanges:
- if (dataRow.RowState == DataRowState.Unchanged) {
- // SQLBU 500706: DataTable internal index is corrupted: '8'
- // if ListChanged event deletes dataRow
- this.SetOldRecord(dataRow, recordNo); // do not fire event
- this.SetNewRecord(dataRow, recordNo, DataRowAction.Change, false, false);
- }
- else { // if modified/ added / deleted we want this operation to fire event (just for LoadOption.PreserveCurrentValues)
- this.SetOldRecord(dataRow, recordNo);
- }
- break;
- default:
- throw ExceptionBuilder.ArgumentOutOfRange("LoadOption");
- }
- if (hasError) {
- string error = Res.GetString(Res.Load_ReadOnlyDataModified);
- if (dataRow.RowError.Length == 0) { // WebData 112272, append the row error
- dataRow.RowError = error;
- }
- else {
- dataRow.RowError += " ]:[ " + error ;
- }
- foreach(DataColumn dc in this.Columns) {
- if (dc.ReadOnly && !dc.Computed)
- dataRow.SetColumnError(dc, error);
- }
- }
- drcevent = RaiseRowChanged(drcevent, dataRow, action);
- if (action == DataRowAction.Nothing) { // RaiseRowChanged does not fire for DataRowAction.Nothing
- dataRow.inChangingEvent = true;
- try {
- OnRowChanged(drcevent, dataRow, action);
- }
- finally {
- dataRow.inChangingEvent = false;
- }
- }
- }
- public DataTableReader CreateDataReader() {
- return new DataTableReader(this);
- }
- public void WriteXml(Stream stream)
- {
- WriteXml(stream, XmlWriteMode.IgnoreSchema, false);
- }
- public void WriteXml(Stream stream, bool writeHierarchy)
- {
- WriteXml(stream, XmlWriteMode.IgnoreSchema, writeHierarchy);
- }
- public void WriteXml(TextWriter writer)
- {
- WriteXml(writer, XmlWriteMode.IgnoreSchema, false);
- }
- public void WriteXml(TextWriter writer, bool writeHierarchy)
- {
- WriteXml(writer, XmlWriteMode.IgnoreSchema, writeHierarchy);
- }
- public void WriteXml(XmlWriter writer)
- {
- WriteXml(writer, XmlWriteMode.IgnoreSchema, false);
- }
- public void WriteXml(XmlWriter writer, bool writeHierarchy)
- {
- WriteXml(writer, XmlWriteMode.IgnoreSchema, writeHierarchy);
- }
- [ResourceExposure(ResourceScope.Machine)]
- [ResourceConsumption(ResourceScope.Machine)]
- public void WriteXml(String fileName)
- {
- WriteXml(fileName, XmlWriteMode.IgnoreSchema, false);
- }
- [ResourceExposure(ResourceScope.Machine)]
- [ResourceConsumption(ResourceScope.Machine)]
- public void WriteXml(String fileName, bool writeHierarchy)
- {
- WriteXml(fileName, XmlWriteMode.IgnoreSchema, writeHierarchy);
- }
- public void WriteXml(Stream stream, XmlWriteMode mode)
- {
- WriteXml(stream, mode, false);
- }
- public void WriteXml(Stream stream, XmlWriteMode mode, bool writeHierarchy)
- {
- if (stream != null) {
- XmlTextWriter w = new XmlTextWriter(stream, null) ;
- w.Formatting = Formatting.Indented;
- WriteXml( w, mode, writeHierarchy);
- }
- }
- public void WriteXml(TextWriter writer, XmlWriteMode mode)
- {
- WriteXml(writer, mode, false);
- }
- public void WriteXml(TextWriter writer, XmlWriteMode mode, bool writeHierarchy)
- {
- if (writer != null) {
- XmlTextWriter w = new XmlTextWriter(writer) ;
- w.Formatting = Formatting.Indented;
- WriteXml(w, mode, writeHierarchy);
- }
- }
- public void WriteXml(XmlWriter writer, XmlWriteMode mode)
- {
- WriteXml(writer, mode, false);
- }
- public void WriteXml(XmlWriter writer, XmlWriteMode mode, bool writeHierarchy)
- {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.WriteXml|API> %d#, mode=%d{ds.XmlWriteMode}\n", ObjectID, (int)mode);
- try{
- if (this.tableName.Length == 0) {
- throw ExceptionBuilder.CanNotSerializeDataTableWithEmptyName();
- }
- // Generate SchemaTree and write it out
- if (writer != null) {
- if (mode == XmlWriteMode.DiffGram) { // FIX THIS
- // Create and save the updates
- new NewDiffgramGen(this, writeHierarchy).Save(writer, this);
- }
- else {
- // Create and save xml data
- if (mode == XmlWriteMode.WriteSchema) {
- DataSet ds = null;
- string tablenamespace = this.tableNamespace;
- if (null == this.DataSet) {
- ds = new DataSet();
- // if user set values on DataTable, it isn't necessary
- // to set them on the DataSet because they won't be inherited
- // but it is simpler to set them in both places
- // if user did not set values on DataTable, it is required
- // to set them on the DataSet so the table will inherit
- // the value already on the Datatable
- ds.SetLocaleValue(_culture, _cultureUserSet);
- ds.CaseSensitive = this.CaseSensitive;
- ds.Namespace = this.Namespace;
- ds.RemotingFormat = this.RemotingFormat;
- ds.Tables.Add(this);
- }
- if (writer != null) {
- XmlDataTreeWriter xmldataWriter = new XmlDataTreeWriter(this, writeHierarchy);
- xmldataWriter.Save(writer, /*mode == XmlWriteMode.WriteSchema*/true);
- }
- if (null != ds) {
- ds.Tables.Remove(this);
- this.tableNamespace = tablenamespace;
- }
- }
- else {
- XmlDataTreeWriter xmldataWriter = new XmlDataTreeWriter(this, writeHierarchy);
- xmldataWriter.Save(writer,/*mode == XmlWriteMode.WriteSchema*/ false);
- }
- }
- }
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- [ResourceExposure(ResourceScope.Machine)]
- [ResourceConsumption(ResourceScope.Machine)]
- public void WriteXml(String fileName, XmlWriteMode mode)
- {
- WriteXml(fileName, mode, false);
- }
- [ResourceExposure(ResourceScope.Machine)]
- [ResourceConsumption(ResourceScope.Machine)]
- public void WriteXml(String fileName, XmlWriteMode mode, bool writeHierarchy)
- {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.WriteXml|API> %d#, fileName='%ls', mode=%d{ds.XmlWriteMode}\n", ObjectID, fileName, (int)mode);
- try {
- using(XmlTextWriter xw = new XmlTextWriter( fileName, null )) {
- xw.Formatting = Formatting.Indented;
- xw.WriteStartDocument(true);
- WriteXml(xw, mode, writeHierarchy);
- xw.WriteEndDocument();
- }
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- public void WriteXmlSchema(Stream stream) {
- WriteXmlSchema(stream, false);
- }
- public void WriteXmlSchema(Stream stream, bool writeHierarchy)
- {
- if (stream == null)
- return;
- XmlTextWriter w = new XmlTextWriter(stream, null) ;
- w.Formatting = Formatting.Indented;
- WriteXmlSchema( w, writeHierarchy );
- }
- public void WriteXmlSchema( TextWriter writer ) {
- WriteXmlSchema( writer, false );
- }
- public void WriteXmlSchema( TextWriter writer, bool writeHierarchy )
- {
- if (writer == null)
- return;
- XmlTextWriter w = new XmlTextWriter(writer);
- w.Formatting = Formatting.Indented;
- WriteXmlSchema( w, writeHierarchy );
- }
- private bool CheckForClosureOnExpressions(DataTable dt, bool writeHierarchy) {
- List<DataTable> tableList = new List<DataTable>();
- tableList.Add(dt);
- if (writeHierarchy) { // WebData 112161
- CreateTableList(dt, tableList);
- }
- return CheckForClosureOnExpressionTables(tableList);
- }
- private bool CheckForClosureOnExpressionTables(List<DataTable> tableList) {
- Debug.Assert(tableList != null, "tableList shouldnot be null");
- foreach(DataTable datatable in tableList) {
- foreach(DataColumn dc in datatable.Columns) {
- if (dc.Expression.Length != 0) {
- DataColumn[] dependency = dc.DataExpression.GetDependency();
- for (int j = 0; j < dependency.Length; j++) {
- if (!(tableList.Contains(dependency[j].Table))) {
- return false;
- }
- }
- }
- }
- }
- return true;
- }
- public void WriteXmlSchema(XmlWriter writer) {
- WriteXmlSchema(writer, false);
- }
- public void WriteXmlSchema(XmlWriter writer, bool writeHierarchy)
- {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.WriteXmlSchema|API> %d#\n", ObjectID);
- try{
- if (this.tableName.Length == 0) {
- throw ExceptionBuilder.CanNotSerializeDataTableWithEmptyName();
- }
- if (!CheckForClosureOnExpressions(this, writeHierarchy)) {
- throw ExceptionBuilder.CanNotSerializeDataTableHierarchy();
- }
- DataSet ds = null;
- string tablenamespace = this.tableNamespace;//SQL BU Defect Tracking 286968
- // Generate SchemaTree and write it out
- if (null == this.DataSet) {
- ds = new DataSet();
- // if user set values on DataTable, it isn't necessary
- // to set them on the DataSet because they won't be inherited
- // but it is simpler to set them in both places
- // if user did not set values on DataTable, it is required
- // to set them on the DataSet so the table will inherit
- // the value already on the Datatable
- ds.SetLocaleValue(_culture, _cultureUserSet);
- ds.CaseSensitive = this.CaseSensitive;
- ds.Namespace = this.Namespace;
- ds.RemotingFormat = this.RemotingFormat;
- ds.Tables.Add(this);
- }
- if (writer != null) {
- XmlTreeGen treeGen = new XmlTreeGen(SchemaFormat.Public);
- treeGen.Save(null, this, writer, writeHierarchy);
- }
- if (null != ds) {
- ds.Tables.Remove(this);
- this.tableNamespace = tablenamespace;
- }
- }
- finally {
- Bid.ScopeLeave(ref hscp);
- }
- }
- [ResourceExposure(ResourceScope.Machine)]
- [ResourceConsumption(ResourceScope.Machine)]
- public void WriteXmlSchema(String fileName) {
- WriteXmlSchema(fileName, false);
- }
- [ResourceExposure(ResourceScope.Machine)]
- [ResourceConsumption(ResourceScope.Machine)]
- public void WriteXmlSchema(String fileName, bool writeHierarchy)
- {
- XmlTextWriter xw = new XmlTextWriter( fileName, null );
- try {
- xw.Formatting = Formatting.Indented;
- xw.WriteStartDocument(true);
- WriteXmlSchema(xw, writeHierarchy);
- xw.WriteEndDocument();
- }
- finally {
- xw.Close();
- }
- }
- public XmlReadMode ReadXml(Stream stream)
- {
- if (stream == null)
- return XmlReadMode.Auto;
- return ReadXml( new XmlTextReader(stream), false);
- }
- public XmlReadMode ReadXml(TextReader reader)
- {
- if (reader == null)
- return XmlReadMode.Auto;
- return ReadXml( new XmlTextReader(reader), false);
- }
- [ResourceExposure(ResourceScope.Machine)]
- [ResourceConsumption(ResourceScope.Machine)]
- public XmlReadMode ReadXml(string fileName)
- {
- XmlTextReader xr = new XmlTextReader(fileName);
- try {
- return ReadXml( xr , false);
- }
- finally {
- xr.Close();
- }
- }
- public XmlReadMode ReadXml(XmlReader reader)
- {
- return ReadXml(reader, false);
- }
- private void RestoreConstraint(bool originalEnforceConstraint) {
- if (this.DataSet != null) {
- this.DataSet.EnforceConstraints = originalEnforceConstraint;
- }
- else {
- this.EnforceConstraints = originalEnforceConstraint;
- }
- }
- private bool IsEmptyXml(XmlReader reader) {
- if (reader.IsEmptyElement) {
- if (reader.AttributeCount == 0 || (reader.LocalName == Keywords.DIFFGRAM && reader.NamespaceURI == Keywords.DFFNS)) {
- return true;
- }
- if (reader.AttributeCount == 1) {
- reader.MoveToAttribute(0);
- if ((this.Namespace == reader.Value) &&
- (this.Prefix == reader.LocalName) &&
- (reader.Prefix == Keywords.XMLNS) &&
- (reader.NamespaceURI == Keywords.XSD_XMLNS_NS))
- return true;
- }
- }
- return false;
- }
- internal XmlReadMode ReadXml(XmlReader reader, bool denyResolving)
- {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.ReadXml|INFO> %d#, denyResolving=%d{bool}\n", ObjectID, denyResolving);
- try {
- DataTable.RowDiffIdUsageSection rowDiffIdUsage = new DataTable.RowDiffIdUsageSection();
- try {
- bool fDataFound = false;
- bool fSchemaFound = false;
- bool fDiffsFound = false;
- bool fIsXdr = false;
- int iCurrentDepth = -1;
- XmlReadMode ret = XmlReadMode.Auto;
- // clear the hashtable to avoid conflicts between diffgrams, SqlHotFix 782
- rowDiffIdUsage.Prepare(this);
- if (reader == null)
- return ret;
- bool originalEnforceConstraint = false;
- if (this.DataSet != null) {
- originalEnforceConstraint = this.DataSet.EnforceConstraints;
- this.DataSet.EnforceConstraints = false;
- }
- else {
- originalEnforceConstraint = this.EnforceConstraints;
- this.EnforceConstraints = false;
- }
- if (reader is XmlTextReader)
- ((XmlTextReader) reader).WhitespaceHandling = WhitespaceHandling.Significant;
- XmlDocument xdoc = new XmlDocument(); // we may need this to infer the schema
- XmlDataLoader xmlload = null;
- reader.MoveToContent();
- if (Columns.Count == 0) {
- if (IsEmptyXml(reader)) {
- reader.Read();
- return ret;
- }
- }
- if (reader.NodeType == XmlNodeType.Element) {
- iCurrentDepth = reader.Depth;
- if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
- if (Columns.Count == 0) {
- if (reader.IsEmptyElement) {
- reader.Read();
- return XmlReadMode.DiffGram;
- }
- throw ExceptionBuilder.DataTableInferenceNotSupported();
- }
- this.ReadXmlDiffgram(reader);
- // read the closing tag of the current element
- ReadEndElement(reader);
- RestoreConstraint(originalEnforceConstraint);
- return XmlReadMode.DiffGram;
- }
- // if reader points to the schema load it
- if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI==Keywords.XDRNS) {
- // load XDR schema and exit
- ReadXDRSchema(reader);
- RestoreConstraint(originalEnforceConstraint);
- return XmlReadMode.ReadSchema; //since the top level element is a schema return
- }
- if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI==Keywords.XSDNS) {
- // load XSD schema and exit
- ReadXmlSchema(reader, denyResolving);
- RestoreConstraint(originalEnforceConstraint);
- return XmlReadMode.ReadSchema; //since the top level element is a schema return
- }
- if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal)) {
- if (this.DataSet != null) { // we should not throw for constraint, we already will throw for unsupported schema, so restore enforce cost, but not via property
- this.DataSet.RestoreEnforceConstraints(originalEnforceConstraint);
- }
- else {
- this.enforceConstraints = originalEnforceConstraint;
- }
- throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
- }
- // now either the top level node is a table and we load it through dataReader...
- // ... or backup the top node and all its attributes because we may need to InferSchema
- XmlElement topNode = xdoc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
- if (reader.HasAttributes) {
- int attrCount = reader.AttributeCount;
- for (int i=0;i<attrCount;i++) {
- reader.MoveToAttribute(i);
- if (reader.NamespaceURI.Equals(Keywords.XSD_XMLNS_NS))
- topNode.SetAttribute(reader.Name, reader.GetAttribute(i));
- else {
- XmlAttribute attr = topNode.SetAttributeNode(reader.LocalName, reader.NamespaceURI);
- attr.Prefix = reader.Prefix;
- attr.Value = reader.GetAttribute(i);
- }
- }
- }
- reader.Read();
- while(MoveToElement(reader, iCurrentDepth)) {
- if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
- this.ReadXmlDiffgram(reader);
- // read the closing tag of the current element
- ReadEndElement(reader);
- RestoreConstraint(originalEnforceConstraint);
- return XmlReadMode.DiffGram;
- }
- // if reader points to the schema load it...
- if (!fSchemaFound && !fDataFound && reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI==Keywords.XDRNS) {
- // load XDR schema and exit
- ReadXDRSchema(reader);
- fSchemaFound = true;
- fIsXdr = true;
- continue;
- }
- if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI==Keywords.XSDNS) {
- // load XSD schema and exit
- ReadXmlSchema(reader, denyResolving);
- fSchemaFound = true;
- continue;
- }
- if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal)) {
- if (this.DataSet != null) { // we should not throw for constraint, we already will throw for unsupported schema, so restore enforce cost, but not via property
- this.DataSet.RestoreEnforceConstraints(originalEnforceConstraint);
- }
- else {
- this.enforceConstraints = originalEnforceConstraint;
- }
- throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
- }
- if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
- this.ReadXmlDiffgram(reader);
- fDiffsFound = true;
- ret = XmlReadMode.DiffGram;
- }
- else {
- // we found data here
- fDataFound = true;
- if (!fSchemaFound && Columns.Count == 0) {
- XmlNode node = xdoc.ReadNode(reader);
- topNode.AppendChild(node);
- }
- else {
- if (xmlload == null)
- xmlload = new XmlDataLoader(this, fIsXdr, topNode, false);
- xmlload.LoadData(reader);
- if (fSchemaFound)
- ret = XmlReadMode.ReadSchema;
- else
- ret = XmlReadMode.IgnoreSchema;
- }
- }
- }
- // read the closing tag of the current element
- ReadEndElement(reader);
- // now top node contains the data part
- xdoc.AppendChild(topNode);
- if (!fSchemaFound && Columns.Count == 0) {
- if (IsEmptyXml(reader)) {
- reader.Read();
- return ret;
- }
- throw ExceptionBuilder.DataTableInferenceNotSupported();
- }
- if (xmlload == null)
- xmlload = new XmlDataLoader(this, fIsXdr, false);
- // so we InferSchema
- if (!fDiffsFound) {// we need to add support for inference here
- }
- }
- RestoreConstraint(originalEnforceConstraint);
- return ret;
- }
- finally {
- rowDiffIdUsage.Cleanup();
- }
- }
- finally{
- Bid.ScopeLeave(ref hscp);
- }
- }
- internal XmlReadMode ReadXml(XmlReader reader, XmlReadMode mode, bool denyResolving)
- {
- DataTable.RowDiffIdUsageSection rowDiffIdUsage = new DataTable.RowDiffIdUsageSection();
- try {
- bool fSchemaFound = false;
- bool fDataFound = false;
- bool fIsXdr = false;
- int iCurrentDepth = -1;
- XmlReadMode ret = mode;
- // Dev11 904428: prepare and cleanup rowDiffId hashtable
- rowDiffIdUsage.Prepare(this);
- if (reader == null)
- return ret;
- bool originalEnforceConstraint = false;
- if (this.DataSet != null) {
- originalEnforceConstraint = this.DataSet.EnforceConstraints;
- this.DataSet.EnforceConstraints = false;
- }
- else {
- originalEnforceConstraint = this.EnforceConstraints;
- this.EnforceConstraints = false;
- }
- if (reader is XmlTextReader)
- ((XmlTextReader) reader).WhitespaceHandling = WhitespaceHandling.Significant;
- XmlDocument xdoc = new XmlDocument(); // we may need this to infer the schema
- if ((mode != XmlReadMode.Fragment) && (reader.NodeType == XmlNodeType.Element))
- iCurrentDepth = reader.Depth;
- reader.MoveToContent();
- if (Columns.Count == 0) {
- if (IsEmptyXml(reader)) {
- reader.Read();
- return ret;
- }
- }
- XmlDataLoader xmlload = null;
- if (reader.NodeType == XmlNodeType.Element) {
- XmlElement topNode = null;
- if (mode == XmlReadMode.Fragment) {
- xdoc.AppendChild(xdoc.CreateElement("ds_sqlXmlWraPPeR"));
- topNode = xdoc.DocumentElement;
- }
- else { //handle the top node
- if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
- if ((mode == XmlReadMode.DiffGram) || (mode == XmlReadMode.IgnoreSchema)) {
- if (Columns.Count == 0) {
- if(reader.IsEmptyElement) {
- reader.Read();
- return XmlReadMode.DiffGram;
- }
- throw ExceptionBuilder.DataTableInferenceNotSupported();
- }
- this.ReadXmlDiffgram(reader);
- // read the closing tag of the current element
- ReadEndElement(reader);
- }
- else {
- reader.Skip();
- }
- RestoreConstraint(originalEnforceConstraint);
- return ret;
- }
- if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI==Keywords.XDRNS) {
- // load XDR schema and exit
- if ((mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema)) {
- ReadXDRSchema(reader);
- }
- else {
- reader.Skip();
- }
- RestoreConstraint(originalEnforceConstraint);
- return ret; //since the top level element is a schema return
- }
- if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI==Keywords.XSDNS) {
- // load XSD schema and exit
- if ((mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema)) {
- ReadXmlSchema(reader, denyResolving);
- }
- else
- reader.Skip();
- RestoreConstraint(originalEnforceConstraint);
- return ret; //since the top level element is a schema return
- }
- if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal)) {
- if (this.DataSet != null) { // we should not throw for constraint, we already will throw for unsupported schema, so restore enforce cost, but not via property
- this.DataSet.RestoreEnforceConstraints(originalEnforceConstraint);
- }
- else {
- this.enforceConstraints = originalEnforceConstraint;
- }
- throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
- }
- // now either the top level node is a table and we load it through dataReader...
- // ... or backup the top node and all its attributes
- topNode = xdoc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
- if (reader.HasAttributes) {
- int attrCount = reader.AttributeCount;
- for (int i=0;i<attrCount;i++) {
- reader.MoveToAttribute(i);
- if (reader.NamespaceURI.Equals(Keywords.XSD_XMLNS_NS))
- topNode.SetAttribute(reader.Name, reader.GetAttribute(i));
- else {
- XmlAttribute attr = topNode.SetAttributeNode(reader.LocalName, reader.NamespaceURI);
- attr.Prefix = reader.Prefix;
- attr.Value = reader.GetAttribute(i);
- }
- }
- }
- reader.Read();
- }
- while(MoveToElement(reader, iCurrentDepth)) {
- if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI==Keywords.XDRNS) {
- // load XDR schema
- if (!fSchemaFound && !fDataFound && (mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema)) {
- ReadXDRSchema(reader);
- fSchemaFound = true;
- fIsXdr = true;
- }
- else {
- reader.Skip();
- }
- continue;
- }
- if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI==Keywords.XSDNS) {
- // load XSD schema and exit
- if ((mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema)) {
- ReadXmlSchema(reader, denyResolving);
- fSchemaFound = true;
- }
- else {
- reader.Skip();
- }
- continue;
- }
- if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
- if ((mode == XmlReadMode.DiffGram) || (mode == XmlReadMode.IgnoreSchema)) {
- if (Columns.Count == 0) {
- if(reader.IsEmptyElement) {
- reader.Read();
- return XmlReadMode.DiffGram;
- }
- throw ExceptionBuilder.DataTableInferenceNotSupported();
- }
- this.ReadXmlDiffgram(reader);
- ret = XmlReadMode.DiffGram;
- }
- else {
- reader.Skip();
- }
- continue;
- }
- if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal)) {
- if (this.DataSet != null) { // we should not throw for constraint, we already will throw for unsupported schema, so restore enforce cost, but not via property
- this.DataSet.RestoreEnforceConstraints(originalEnforceConstraint);
- }
- else {
- this.enforceConstraints = originalEnforceConstraint;
- }
- throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
- }
- if (mode == XmlReadMode.DiffGram) {
- reader.Skip();
- continue; // we do not read data in diffgram mode
- }
- // if we are here we found some data
- fDataFound = true;
- if (mode == XmlReadMode.InferSchema) { //save the node in DOM until the end;
- XmlNode node = xdoc.ReadNode(reader);
- topNode.AppendChild(node);
- }
- else {
- if (Columns.Count == 0) {
- throw ExceptionBuilder.DataTableInferenceNotSupported();
- }
- if (xmlload == null)
- xmlload = new XmlDataLoader(this, fIsXdr, topNode, mode == XmlReadMode.IgnoreSchema);
- xmlload.LoadData(reader);
- }
- } //end of the while
- // read the closing tag of the current element
- ReadEndElement(reader);
- // now top node contains the data part
- xdoc.AppendChild(topNode);
- if (xmlload == null)
- xmlload = new XmlDataLoader(this, fIsXdr, mode == XmlReadMode.IgnoreSchema);
- if (mode == XmlReadMode.DiffGram) {
- // we already got the diffs through XmlReader interface
- RestoreConstraint(originalEnforceConstraint);
- return ret;
- }
- //todo
- // Load Data
- if (mode == XmlReadMode.InferSchema) {
- if (Columns.Count == 0) {
- throw ExceptionBuilder.DataTableInferenceNotSupported();
- }
- // [....] xmlload.InferSchema(xdoc, null);
- // [....] xmlload.LoadData(xdoc);
- }
- }
- RestoreConstraint(originalEnforceConstraint);
- return ret;
- }
- finally {
- // Dev11 904428: prepare and cleanup rowDiffId hashtable
- rowDiffIdUsage.Cleanup();
- }
- }
- internal void ReadEndElement(XmlReader reader) {
- while (reader.NodeType == XmlNodeType.Whitespace) {
- reader.Skip();
- }
- if (reader.NodeType == XmlNodeType.None) {
- reader.Skip();
- }
- else if (reader.NodeType == XmlNodeType.EndElement) {
- reader.ReadEndElement();
- }
- }
- internal void ReadXDRSchema(XmlReader reader) {
- XmlDocument xdoc = new XmlDocument(); // we may need this to infer the schema
- XmlNode schNode = xdoc.ReadNode(reader);;
- //consume and ignore it - No support
- }
- internal bool MoveToElement(XmlReader reader, int depth) {
- while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement && reader.NodeType != XmlNodeType.Element && reader.Depth > depth) {
- reader.Read();
- }
- return (reader.NodeType == XmlNodeType.Element);
- }
- private void ReadXmlDiffgram(XmlReader reader) { // fill correctly
- int d = reader.Depth;
- bool fEnforce = this.EnforceConstraints;
- this.EnforceConstraints =false;
- DataTable newDt;
- bool isEmpty;
- if (this.Rows.Count == 0) {
- isEmpty = true;
- newDt = this;
- }
- else {
- isEmpty = false;
- newDt = this.Clone();
- newDt.EnforceConstraints = false;
- }
- newDt.Rows.nullInList = 0;
- reader.MoveToContent();
- if ((reader.LocalName != Keywords.DIFFGRAM) && (reader.NamespaceURI != Keywords.DFFNS))
- return;
- reader.Read();
- if (reader.NodeType == XmlNodeType.Whitespace) {
- MoveToElement(reader, reader.Depth - 1 /*iCurrentDepth*/); // skip over whitespaces.
- }
- newDt.fInLoadDiffgram = true;
- if (reader.Depth > d) {
- if ((reader.NamespaceURI != Keywords.DFFNS) && (reader.NamespaceURI != Keywords.MSDNS)) {
- //we should be inside the dataset part
- XmlDocument xdoc = new XmlDocument();
- XmlElement node = xdoc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
- reader.Read();
- if (reader.Depth-1 > d) {
- XmlDataLoader xmlload = new XmlDataLoader(newDt, false, node, false);
- xmlload.isDiffgram = true; // turn on the special processing
- xmlload.LoadData(reader);
- }
- ReadEndElement(reader);
- }
- if (((reader.LocalName == Keywords.SQL_BEFORE) && (reader.NamespaceURI == Keywords.DFFNS)) ||
- ((reader.LocalName == Keywords.MSD_ERRORS) && (reader.NamespaceURI == Keywords.DFFNS)))
- {
- //this will consume the changes and the errors part
- XMLDiffLoader diffLoader = new XMLDiffLoader();
- diffLoader.LoadDiffGram(newDt, reader);
- }
- // get to the closing diff tag
- while(reader.Depth > d) {
- reader.Read();
- }
- // read the closing tag
- ReadEndElement(reader);
- }
- if (newDt.Rows.nullInList > 0)
- throw ExceptionBuilder.RowInsertMissing(newDt.TableName);
- newDt.fInLoadDiffgram = false;
- List<DataTable> tableList = new List<DataTable>();
- tableList.Add(this);
- CreateTableList(this, tableList);
- // this is terrible, optimize it
- for (int i = 0; i < tableList.Count ; i++) {
- DataRelation[] relations = tableList[i].NestedParentRelations;
- foreach(DataRelation rel in relations) {
- if (rel != null && rel.ParentTable == tableList[i]) {
- foreach (DataRow r in tableList[i].Rows) {
- foreach (DataRelation rel2 in relations) {
- r.CheckForLoops(rel2);
- }
- }
- }
- }
- }
- if (!isEmpty) {
- this.Merge(newDt);
- }
- this.EnforceConstraints = fEnforce;
- }
- internal void ReadXSDSchema(XmlReader reader, bool denyResolving) {
- XmlSchemaSet sSet = new XmlSchemaSet();
- while (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI==Keywords.XSDNS) {
- XmlSchema s = XmlSchema.Read(reader, null);
- sSet.Add(s);
- //read the end tag
- ReadEndElement(reader);
- }
- sSet.Compile();
- XSDSchema schema = new XSDSchema();
- schema.LoadSchema(sSet, this);
- }
- public void ReadXmlSchema(Stream stream)
- {
- if (stream == null)
- return;
- ReadXmlSchema( new XmlTextReader( stream ), false );
- }
- public void ReadXmlSchema(TextReader reader)
- {
- if (reader == null)
- return;
- ReadXmlSchema( new XmlTextReader( reader ), false );
- }
- [ResourceExposure(ResourceScope.Machine)]
- [ResourceConsumption(ResourceScope.Machine)]
- public void ReadXmlSchema(String fileName)
- {
- XmlTextReader xr = new XmlTextReader(fileName);
- try {
- ReadXmlSchema( xr, false );
- }
- finally {
- xr.Close();
- }
- }
- public void ReadXmlSchema(XmlReader reader)
- {
- ReadXmlSchema(reader, false);
- }
- internal void ReadXmlSchema(XmlReader reader, bool denyResolving)
- {
- IntPtr hscp;
- Bid.ScopeEnter(out hscp, "<ds.DataTable.ReadXmlSchema|INFO> %d#, denyResolving=%d{bool}\n", ObjectID, denyResolving);
- try{
- DataSet ds = new DataSet();
- SerializationFormat cachedRemotingFormat = this.RemotingFormat;
- // fxcop: ReadXmlSchema will provide the CaseSensitive, Locale, Namespace information
- ds.ReadXmlSchema(reader, denyResolving);
- string CurrentTableFullName = ds.MainTableName;
- if (Common.ADP.IsEmpty(this.tableName) && Common.ADP.IsEmpty(CurrentTableFullName))
- return;
- DataTable currentTable = null;
- if (!Common.ADP.IsEmpty(this.tableName)) {
- if (!Common.ADP.IsEmpty(this.Namespace)) {
- currentTable = ds.Tables[this.tableName, this.Namespace];
- }
- else {//SQL BU defect tracking 240293
- int tableIndex = ds.Tables.InternalIndexOf(this.tableName);
- if (tableIndex > -1) {
- currentTable = ds.Tables[tableIndex];
- }
- }
- }
- else{ //!Common.ADP.IsEmpty(CurrentTableFullName)
- string CurrentTableNamespace = "";
- int nsSeperator = CurrentTableFullName.IndexOf(':');
- if (nsSeperator > -1) {
- CurrentTableNamespace = CurrentTableFullName.Substring(0, nsSeperator);
- }
- string CurrentTableName = CurrentTableFullName.Substring(nsSeperator + 1, CurrentTableFullName.Length - nsSeperator -1);
- currentTable = ds.Tables[CurrentTableName, CurrentTableNamespace];
- }
- if (currentTable == null) { // bug fix :99186
- string qTableName = string.Empty;
- if (!Common.ADP.IsEmpty(this.tableName)) {
- qTableName = (this.Namespace.Length > 0)? (this.Namespace + ":" + this.tableName):this.tableName;
- }
- else {
- qTableName = CurrentTableFullName ;
- }
- throw ExceptionBuilder.TableNotFound(qTableName);
- }
- currentTable._remotingFormat = cachedRemotingFormat;
- List<DataTable> tableList = new List<DataTable>();
- tableList.Add(currentTable);
- CreateTableList(currentTable, tableList);
- List<DataRelation> relationList = new List<DataRelation>();
- CreateRelationList(tableList, relationList);
- if (relationList.Count == 0) {
- if (this.Columns.Count == 0) {
- DataTable tempTable = currentTable;
- if (tempTable != null)
- tempTable.CloneTo(this, null, false); // we may have issue Amir
- if (this.DataSet == null && this.tableNamespace == null) { // webdata 105506
- // for standalone table, clone wont get these correctly, since they may come with inheritance
- this.tableNamespace = tempTable.Namespace;
- }
- }
- return;
- }
- else {
- if (Common.ADP.IsEmpty(this.TableName)) {
- this.TableName = currentTable.TableName;
- if (!Common.ADP.IsEmpty(currentTable.Namespace)) {
- this.Namespace = currentTable.Namespace;
- }
- }
- if (this.DataSet == null) {
- DataSet dataset = new DataSet(ds.DataSetName);
- // webdata 105506
- // if user set values on DataTable, it isn't necessary
- // to set them on the DataSet because they won't be inherited
- // but it is simpler to set them in both places
- // if user did not set values on DataTable, it is required
- // to set them on the DataSet so the table will inherit
- // the value already on the Datatable
- dataset.SetLocaleValue(ds.Locale, ds.ShouldSerializeLocale());
- dataset.CaseSensitive = ds.CaseSensitive;
- dataset.Namespace = ds.Namespace;
- dataset.mainTableName = ds.mainTableName;
- dataset.RemotingFormat = ds.RemotingFormat;
- dataset.Tables.Add(this);
- }
- DataTable targetTable = CloneHierarchy(currentTable, this.DataSet, null);
- foreach(DataTable tempTable in tableList) {
- DataTable destinationTable = this.DataSet.Tables[tempTable.tableName, tempTable.Namespace];
- DataTable sourceTable = ds.Tables[tempTable.tableName, tempTable.Namespace];
- foreach(Constraint tempConstrain in sourceTable.Constraints) {
- ForeignKeyConstraint fkc = tempConstrain as ForeignKeyConstraint; // we have already cloned the UKC when cloning the datatable
- if (fkc != null) {
- if (fkc.Table != fkc.RelatedTable) {
- if (tableList.Contains(fkc.Table) && tableList.Contains(fkc.RelatedTable)) {
- ForeignKeyConstraint newFKC = (ForeignKeyConstraint)fkc.Clone(destinationTable.DataSet);
- if (!destinationTable.Constraints.Contains(newFKC.ConstraintName))
- destinationTable.Constraints.Add(newFKC); // we know that the dest table is already in the table
- }
- }
- }
- }
- }
- foreach(DataRelation rel in relationList) {
- if (!this.DataSet.Relations.Contains(rel.RelationName))
- this.DataSet.Relations.Add(rel.Clone(this.DataSet));
- }
- bool hasExternaldependency = false;
- foreach(DataTable tempTable in tableList) {
- foreach(DataColumn dc in tempTable.Columns) {
- hasExternaldependency = false;
- if (dc.Expression.Length != 0) {
- DataColumn[] dependency = dc.DataExpression.GetDependency();
- for (int j = 0; j < dependency.Length; j++) {
- if (!tableList.Contains(dependency[j].Table)) {
- hasExternaldependency = true;
- break;
- }
- }
- }
- if (!hasExternaldependency) {
- this.DataSet.Tables[tempTable.TableName, tempTable.Namespace].Columns[dc.ColumnName].Expression = dc.Expression;
- }
- }
- hasExternaldependency = false;
- }
- }
- }
- finally{
- Bid.ScopeLeave(ref hscp);
- }
- }
- private void CreateTableList(DataTable currentTable, List<DataTable> tableList) {
- foreach( DataRelation r in currentTable.ChildRelations ) {
- if (! tableList.Contains(r.ChildTable)) {
- tableList.Add(r.ChildTable);
- CreateTableList(r.ChildTable, tableList);
- }
- }
- }
- private void CreateRelationList(List<DataTable> tableList, List<DataRelation> relationList) {
- foreach(DataTable table in tableList) {
- foreach( DataRelation r in table.ChildRelations) {
- if (tableList.Contains(r.ChildTable) && tableList.Contains(r.ParentTable)) {
- relationList.Add(r);
- }
- }
- }
- }
- /**************************************************************************
- The V2.0 (no V1.0 or V1.1) WSDL for Untyped DataTable being returned as a result (no parameters)
- <s:element name="anyUserSpecifiedMethodName">
- <!-- This is where parameters go -->
- <s:complexType />
- </s:element>
- <s:element name="anyUserSpecifiedMethodName"+"Response">
- <s:complexType>
- <s:sequence>
- <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result">
- <s:complexType>
- <s:sequence>
- <s:any minOccurs="0" maxOccurs="unbounded" namespace="http://www.w3.org/2001/XMLSchema" processContents="lax" />
- <s:any minOccurs="1" namespace="urn:schemas-microsoft-com:xml-diffgram-v1" processContents="lax" />
- </s:sequence>
- </s:complexType>
- </s:element>
- </s:sequence>
- </s:complexType>
- </s:element>
- Typed DataTable is not supported in WSDL (SQLBU 444636)
- either fails because xsd generates its typed DataTable with an internal parameterless ctor
-
- or System.NullReferenceException: Object reference not set to an instance of an object. (if namespace of StronglyTyped DataTable is not set)
- at System.Data.XmlTreeGen.FindTargetNamespace(DataTable table)
- or System.InvalidOperationException: Schema Id is missing. The schema returned from WebServiceDataSetServer.Service+StudentsDataTable.GetSchema() must have an Id.
- at System.Xml.Serialization.SerializableMapping.RetrieveSerializableSchema()
- *****************************************************************************/
- public static XmlSchemaComplexType GetDataTableSchema(XmlSchemaSet schemaSet) {
- XmlSchemaComplexType type = new XmlSchemaComplexType();
- XmlSchemaSequence sequence = new XmlSchemaSequence();
- XmlSchemaAny any = new XmlSchemaAny();
- any.Namespace = XmlSchema.Namespace;
- any.MinOccurs = 0;
- any.MaxOccurs = Decimal.MaxValue;
- any.ProcessContents = XmlSchemaContentProcessing.Lax;
- sequence.Items.Add(any);
- any = new XmlSchemaAny();
- any.Namespace = Keywords.DFFNS;
- any.MinOccurs = 1; // when recognizing WSDL - MinOccurs="0" denotes DataSet, a MinOccurs="1" for DataTable
- any.ProcessContents = XmlSchemaContentProcessing.Lax;
- sequence.Items.Add(any);
- type.Particle = sequence;
- return type;
- }
- XmlSchema IXmlSerializable.GetSchema() {
- return GetSchema();
- }
- protected virtual XmlSchema GetSchema() {
- if (GetType() == typeof(DataTable)) {
- return null;
- }
- MemoryStream stream = new MemoryStream();
- XmlWriter writer = new XmlTextWriter(stream, null);
- if (writer != null) {
- (new XmlTreeGen(SchemaFormat.WebService)).Save(this, writer);
- }
- stream.Position = 0;
- return XmlSchema.Read(new XmlTextReader(stream), null);
- }
- void IXmlSerializable.ReadXml(XmlReader reader) {
- IXmlTextParser textReader = reader as IXmlTextParser;
- bool fNormalization = true;
- if (textReader != null) {
- fNormalization = textReader.Normalized;
- textReader.Normalized = false;
- }
- ReadXmlSerializable(reader);
- if (textReader != null) {
- textReader.Normalized = fNormalization;
- }
- }
- void IXmlSerializable.WriteXml(XmlWriter writer) {
- WriteXmlSchema(writer, false);
- WriteXml(writer, XmlWriteMode.DiffGram, false);
- }
- protected virtual void ReadXmlSerializable(XmlReader reader) {
- ReadXml(reader, XmlReadMode.DiffGram, true);
- }
- /*
- [
- DefaultValue(false),
- ResCategoryAttribute(Res.DataCategory_Data),
- ResDescriptionAttribute(Res.DataTableSerializeHierarchy)
- ]
- public bool SerializeHierarchy {
- get {
- return this.serializeHierarchy;
- }
- set {
- this.serializeHierarchy = value;
- }
- }
- */
- // RowDiffIdUsageSection & DSRowDiffIdUsageSection Usage:
- //
- // DataTable.[DS]RowDiffIdUsageSection rowDiffIdUsage = new DataTable.[DS]RowDiffIdUsageSection();
- // try {
- // rowDiffIdUsage.Prepare(DataTable or DataSet, depending on type);
- //
- // // code that requires RowDiffId usage
- //
- // }
- // finally {
- // rowDiffIdUsage.Cleanup();
- // }
- //
- // Nested calls are allowed on different tables. For example, user can register to row change events and trigger
- // ReadXml on different table/ds). But, if user code will try to call ReadXml on table that is already in the scope,
- // this code will assert since nested calls on same table are unsupported.
- internal struct RowDiffIdUsageSection
- {
- #if DEBUG
- // This list contains tables currently used in diffgram processing, not including new tables that might be added later during.
- // if diffgram processing is not started, this value must be null. when it starts, relevant method should call Prepare.
- // Notes:
- // * in case of ReadXml on empty DataSet, this list can be initialized as empty (so empty list != null).
- // * only one scope is allowed on single thread, either for datatable or dataset
- // * assert is triggered if same table is added to this list twice
- //
- // do not allocate TLS data in RETAIL bits!
- [ThreadStatic]
- internal static List<DataTable> s_usedTables;
- #endif //DEBUG
- DataTable _targetTable;
- internal void Prepare(DataTable table)
- {
- Debug.Assert(_targetTable == null, "do not reuse this section");
- Debug.Assert(table != null);
- Debug.Assert(table.rowDiffId == null, "rowDiffId wasn't previously cleared");
- #if DEBUG
- Debug.Assert(s_usedTables == null || !s_usedTables.Contains(table),
- "Nested call with same table can cause data corruption!");
- #endif //DEBUG
- #if DEBUG
- if (s_usedTables == null)
- s_usedTables = new List<DataTable>();
- s_usedTables.Add(table);
- #endif //DEBUG
- _targetTable = table;
- table.rowDiffId = null;
- }
- [Conditional("DEBUG")]
- internal void Cleanup()
- {
- // cannot assume target table was set - ThreadAbortException can be raised before Start is called
- if (_targetTable != null)
- {
- #if DEBUG
- Debug.Assert(s_usedTables != null && s_usedTables.Contains(_targetTable), "missing Prepare before Cleanup");
- if (s_usedTables != null)
- {
- s_usedTables.Remove(_targetTable);
- if (s_usedTables.Count == 0)
- s_usedTables = null;
- }
- #endif //DEBUG
- _targetTable.rowDiffId = null;
- }
- }
- [Conditional("DEBUG")]
- internal static void Assert(string message)
- {
- #if DEBUG
- // this code asserts scope was created, but it does not assert that the table was included in it
- // note that in case of DataSet, new tables might be added to the list in which case they won't appear in s_usedTables.
- Debug.Assert(s_usedTables != null, message);
- #endif //DEBUG
- }
- }
- internal struct DSRowDiffIdUsageSection
- {
- DataSet _targetDS;
- internal void Prepare(DataSet ds)
- {
- Debug.Assert(_targetDS == null, "do not reuse this section");
- Debug.Assert(ds != null);
- _targetDS = ds;
- #if DEBUG
- // initialize list of tables out of current tables
- // note: it might remain empty (still initialization is needed for assert to operate)
- if (RowDiffIdUsageSection.s_usedTables == null)
- RowDiffIdUsageSection.s_usedTables = new List<DataTable>();
- #endif //DEBUG
- for (int tableIndex = 0; tableIndex < ds.Tables.Count; ++tableIndex)
- {
- DataTable table = ds.Tables[tableIndex];
- #if DEBUG
- Debug.Assert(!RowDiffIdUsageSection.s_usedTables.Contains(table), "Nested call with same table can cause data corruption!");
- RowDiffIdUsageSection.s_usedTables.Add(table);
- #endif //DEBUG
- Debug.Assert(table.rowDiffId == null, "rowDiffId wasn't previously cleared");
- table.rowDiffId = null;
- }
- }
- [Conditional("DEBUG")]
- internal void Cleanup()
- {
- // cannot assume target was set - ThreadAbortException can be raised before Start is called
- if (_targetDS != null)
- {
- #if DEBUG
- Debug.Assert(RowDiffIdUsageSection.s_usedTables != null, "missing Prepare before Cleanup");
- #endif //DEBUG
- for (int tableIndex = 0; tableIndex < _targetDS.Tables.Count; ++tableIndex)
- {
- DataTable table = _targetDS.Tables[tableIndex];
- #if DEBUG
- // cannot assert that table exists in the usedTables - new tables might be
- // created during diffgram processing in DataSet.ReadXml.
- if (RowDiffIdUsageSection.s_usedTables != null)
- RowDiffIdUsageSection.s_usedTables.Remove(table);
- #endif //DEBUG
- table.rowDiffId = null;
- }
- #if DEBUG
- if (RowDiffIdUsageSection.s_usedTables != null && RowDiffIdUsageSection.s_usedTables.Count == 0)
- RowDiffIdUsageSection.s_usedTables = null; // out-of-scope
- #endif //DEBUG
- }
- }
- }
- internal Hashtable RowDiffId {
- get {
- // assert scope has been created either with RowDiffIdUsageSection.Prepare or DSRowDiffIdUsageSection.Prepare
- RowDiffIdUsageSection.Assert("missing call to RowDiffIdUsageSection.Prepare or DSRowDiffIdUsageSection.Prepare");
- if (rowDiffId == null)
- rowDiffId = new Hashtable();
- return rowDiffId;
- }
- }
- internal int ObjectID {
- get {
- return _objectID;
- }
- }
- internal void AddDependentColumn(DataColumn expressionColumn) {
- if (dependentColumns == null)
- dependentColumns = new List<DataColumn>();
- if (!dependentColumns.Contains(expressionColumn)) {
- // only remember unique columns but expect non-unique columns to be added
- dependentColumns.Add(expressionColumn);
- }
- }
- internal void RemoveDependentColumn(DataColumn expressionColumn) {
- if (dependentColumns != null && dependentColumns.Contains(expressionColumn)) {
- dependentColumns.Remove(expressionColumn);
- }
- }
- internal void EvaluateExpressions() {
- //evaluates all expressions for all rows in table
- // SQLBU 414992: Serious performance issue when calling Merge
- // this improves performance by only computing expressions when they are present
- // and iterating over the rows instead of computing their position multiple times
- if ((null != dependentColumns) && (0 < dependentColumns.Count)) {
- foreach(DataRow row in Rows) {
- // only evaluate original values if different from current.
- if (row.oldRecord != -1 && row.oldRecord != row.newRecord) {
- EvaluateDependentExpressions(dependentColumns, row, DataRowVersion.Original, null);
- }
- if (row.newRecord != -1) {
- EvaluateDependentExpressions(dependentColumns, row, DataRowVersion.Current, null);
- }
- if (row.tempRecord != -1) {
- EvaluateDependentExpressions(dependentColumns, row, DataRowVersion.Proposed, null);
- }
- }
- }
- }
- internal void EvaluateExpressions(DataRow row, DataRowAction action, List<DataRow> cachedRows) {
- // evaluate all expressions for specified row
- if (action == DataRowAction.Add ||
- action == DataRowAction.Change||
- (action == DataRowAction.Rollback && (row.oldRecord!=-1 || row.newRecord!=-1))) {
- // only evaluate original values if different from current.
- if (row.oldRecord != -1 && row.oldRecord != row.newRecord) {
- EvaluateDependentExpressions(dependentColumns, row, DataRowVersion.Original, cachedRows);
- }
- if (row.newRecord != -1) {
- EvaluateDependentExpressions(dependentColumns, row, DataRowVersion.Current, cachedRows);
- }
- if (row.tempRecord != -1) {
- EvaluateDependentExpressions(dependentColumns, row, DataRowVersion.Proposed, cachedRows);
- }
- return;
- }
- else if ((action == DataRowAction.Delete || (action==DataRowAction.Rollback && row.oldRecord==-1 && row.newRecord==-1)) && dependentColumns != null) {
- foreach(DataColumn col in dependentColumns) {
- if (col.DataExpression != null && col.DataExpression.HasLocalAggregate() && col.Table == this) {
- for (int j = 0; j < Rows.Count; j++) {
- DataRow tableRow = Rows[j];
- if (tableRow.oldRecord != -1 && tableRow.oldRecord != tableRow.newRecord) {
- EvaluateDependentExpressions(dependentColumns, tableRow, DataRowVersion.Original, null);
- }
- }
- for (int j = 0; j < Rows.Count; j++)
- {
- DataRow tableRow = Rows[j];
-
- if (tableRow.tempRecord != -1)
- {
- EvaluateDependentExpressions(dependentColumns, tableRow, DataRowVersion.Proposed, null);
- }
- }
- // VSTFDEVDIV911434: Order is important here - we need to update proposed before current
- // Oherwise rows that are in edit state will get ListChanged/PropertyChanged event before default value is changed
- // It is also the reason why we are not doping it in the single loop: EvaluateDependentExpression can update the
- // whole table, if it happens, current for all but first row is updated before proposed value
- for (int j = 0; j < Rows.Count; j++)
- {
- DataRow tableRow = Rows[j];
-
- if (tableRow.newRecord != -1)
- {
- EvaluateDependentExpressions(dependentColumns, tableRow, DataRowVersion.Current, null);
- }
- }
- break;
- }
- }
- if (cachedRows != null) {
- foreach (DataRow relatedRow in cachedRows) {
- if (relatedRow.oldRecord != -1 && relatedRow.oldRecord != relatedRow.newRecord) {
- relatedRow.Table.EvaluateDependentExpressions(relatedRow.Table.dependentColumns, relatedRow, DataRowVersion.Original, null);
- }
- if (relatedRow.newRecord != -1) {
- relatedRow.Table.EvaluateDependentExpressions(relatedRow.Table.dependentColumns, relatedRow, DataRowVersion.Current, null);
- }
- if (relatedRow.tempRecord != -1) {
- relatedRow.Table.EvaluateDependentExpressions(relatedRow.Table.dependentColumns, relatedRow, DataRowVersion.Proposed, null);
- }
- }
- }
- }
- }
- internal void EvaluateExpressions(DataColumn column) {
- // evaluates all rows for expression from specified column
- Debug.Assert(column.Computed, "Only computed columns should be re-evaluated.");
- int count = column.table.Rows.Count;
- if (column.DataExpression.IsTableAggregate() && count > 0) {
- // this value is a constant across the table.
- object aggCurrent = column.DataExpression.Evaluate();
- for (int j = 0; j < count; j++) {
- DataRow row = column.table.Rows[j];
- // only evaluate original values if different from current.
- if (row.oldRecord != -1 && row.oldRecord != row.newRecord) {
- column[row.oldRecord] = aggCurrent;
- }
- if (row.newRecord != -1) {
- column[row.newRecord] = aggCurrent;
- }
- if (row.tempRecord != -1) {
- column[row.tempRecord] = aggCurrent;
- }
- }
- }
- else {
- for (int j = 0; j < count; j++) {
- DataRow row = column.table.Rows[j];
- if (row.oldRecord != -1 && row.oldRecord != row.newRecord) {
- column[row.oldRecord] = column.DataExpression.Evaluate(row, DataRowVersion.Original);
- }
- if (row.newRecord != -1) {
- column[row.newRecord] = column.DataExpression.Evaluate(row, DataRowVersion.Current);
- }
- if (row.tempRecord != -1) {
- column[row.tempRecord] = column.DataExpression.Evaluate(row, DataRowVersion.Proposed);
- }
- }
- }
- // SQLBU 501916 - DataTable internal index is corrupted:'5'
- column.Table.ResetInternalIndexes(column);
- EvaluateDependentExpressions(column);
- }
- internal void EvaluateDependentExpressions(DataColumn column) {
- // DataTable.Clear(), DataRowCollection.Clear() & DataColumn.set_Expression
- if (column.dependentColumns != null) {
- foreach (DataColumn dc in column.dependentColumns) {
- if ((dc.table != null) && !Object.ReferenceEquals(column, dc)) { // SQLBU 502736
- EvaluateExpressions(dc);
- }
- }
- }
- }
- internal void EvaluateDependentExpressions(List<DataColumn> columns, DataRow row, DataRowVersion version, List<DataRow> cachedRows) {
- if (columns == null)
- return;
- //Expression evaluation is done first over same table expressions.
- int count = columns.Count;
- for(int i = 0; i < count; i++) {
- if (columns[i].Table == this) {// if this column is in my table
- DataColumn dc = columns[i];
- if (dc.DataExpression != null && dc.DataExpression.HasLocalAggregate()) {
- // if column expression references a local Table aggregate we need to recalc it for the each row in the local table
- DataRowVersion expressionVersion = (version == DataRowVersion.Proposed) ? DataRowVersion.Default : version;
- bool isConst = dc.DataExpression.IsTableAggregate(); //is expression constant for entire table?
- object newValue = null;
- if (isConst) { //if new value, just compute once
- newValue = dc.DataExpression.Evaluate(row, expressionVersion);
- }
- for (int j = 0; j < Rows.Count; j++) { //evaluate for all rows in the table
- DataRow dr = Rows[j];
- if (dr.RowState == DataRowState.Deleted) {
- continue;
- }
- else if (expressionVersion == DataRowVersion.Original && (dr.oldRecord == -1 || dr.oldRecord == dr.newRecord)) {
- continue;
- }
- if (!isConst) {
- newValue = dc.DataExpression.Evaluate(dr, expressionVersion);
- }
- SilentlySetValue(dr, dc, expressionVersion, newValue);
- }
- }
- else {
- if (row.RowState == DataRowState.Deleted) {
- continue;
- }
- else if (version == DataRowVersion.Original && (row.oldRecord == -1 || row.oldRecord == row.newRecord)) {
- continue;
- }
- SilentlySetValue(row, dc, version, dc.DataExpression == null ? dc.DefaultValue : dc.DataExpression.Evaluate(row, version));
- }
- }
- }
- // now do expression evaluation for expression columns other tables.
- count = columns.Count;
- for(int i = 0; i < count; i++) {
- DataColumn dc = columns[i];
- // if this column is NOT in my table or it is in the table and is not a local aggregate (self refs)
- if (dc.Table != this || (dc.DataExpression != null && !dc.DataExpression.HasLocalAggregate())) {
- DataRowVersion foreignVer = (version == DataRowVersion.Proposed) ? DataRowVersion.Default : version;
- // first - evaluate expressions for cachedRows (deletes & updates)
- if (cachedRows != null) {
- foreach (DataRow cachedRow in cachedRows) {
- if (cachedRow.Table != dc.Table)
- continue;
- // don't update original version if child row doesn't have an oldRecord.
- if (foreignVer == DataRowVersion.Original && cachedRow.newRecord == cachedRow.oldRecord)
- continue;
- if (cachedRow != null && ((cachedRow.RowState != DataRowState.Deleted) && (version != DataRowVersion.Original || cachedRow.oldRecord != -1))) {// if deleted GetRecordFromVersion will throw
- object newValue = dc.DataExpression.Evaluate(cachedRow, foreignVer);
- SilentlySetValue(cachedRow, dc, foreignVer, newValue);
- }
- }
- }
- // next check parent relations
- for (int j = 0; j < ParentRelations.Count; j++) {
- DataRelation relation = ParentRelations[j];
- if (relation.ParentTable != dc.Table)
- continue;
- foreach (DataRow parentRow in row.GetParentRows(relation, version)) {
- if (cachedRows != null && cachedRows.Contains(parentRow))
- continue;
- // don't update original version if child row doesn't have an oldRecord.
- if (foreignVer == DataRowVersion.Original && parentRow.newRecord == parentRow.oldRecord)
- continue;
- if (parentRow != null && ((parentRow.RowState != DataRowState.Deleted) && (version != DataRowVersion.Original || parentRow.oldRecord != -1))) {// if deleted GetRecordFromVersion will throw
- object newValue = dc.DataExpression.Evaluate(parentRow, foreignVer);
- SilentlySetValue(parentRow, dc, foreignVer, newValue);
- }
- }
- }
- // next check child relations
- for (int j = 0; j < ChildRelations.Count; j++) {
- DataRelation relation = ChildRelations[j];
- if (relation.ChildTable != dc.Table)
- continue;
- foreach (DataRow childRow in row.GetChildRows(relation, version)) {
- // don't update original version if child row doesn't have an oldRecord.
- if (cachedRows != null && cachedRows.Contains(childRow))
- continue;
- if (foreignVer == DataRowVersion.Original && childRow.newRecord == childRow.oldRecord)
- continue;
- if (childRow != null && ((childRow.RowState != DataRowState.Deleted) && (version != DataRowVersion.Original || childRow.oldRecord != -1))) { // if deleted GetRecordFromVersion will throw
- object newValue = dc.DataExpression.Evaluate(childRow, foreignVer);
- SilentlySetValue(childRow, dc, foreignVer, newValue);
- }
- }
- }
- }
- }
- }
- }
- }
|