ObjectDataSourceView.cs 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210
  1. //
  2. // System.Web.UI.WebControls.ObjectDataSourceView
  3. //
  4. // Authors:
  5. // Lluis Sanchez Gual ([email protected])
  6. //
  7. // (C) 2005 Novell, Inc. (http://www.novell.com)
  8. //
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining
  11. // a copy of this software and associated documentation files (the
  12. // "Software"), to deal in the Software without restriction, including
  13. // without limitation the rights to use, copy, modify, merge, publish,
  14. // distribute, sublicense, and/or sell copies of the Software, and to
  15. // permit persons to whom the Software is furnished to do so, subject to
  16. // the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be
  19. // included in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. #if NET_2_0
  30. using System;
  31. using System.Reflection;
  32. using System.Collections;
  33. using System.Collections.Specialized;
  34. using System.ComponentModel;
  35. using System.IO;
  36. using System.Data;
  37. using System.Web.Compilation;
  38. namespace System.Web.UI.WebControls
  39. {
  40. public class ObjectDataSourceView : DataSourceView, IStateManager
  41. {
  42. ObjectDataSource owner;
  43. HttpContext context;
  44. Type objectType;
  45. Type dataObjectType;
  46. bool convertNullToDBNull = false;
  47. bool enablePaging = false;
  48. string dataObjectTypeName = null;
  49. string filterExpression = null;
  50. string maximumRowsParameterName = null;
  51. string oldValuesParameterFormatString = null;
  52. string deleteMethod = null;
  53. string insertMethod = null;
  54. string selectCountMethod = null;
  55. string selectMethod = null;
  56. string sortParameterName = null;
  57. string startRowIndexParameterName = null;
  58. string typeName = null;
  59. string updateMethod = null;
  60. bool isTrackingViewState = false;
  61. ParameterCollection selectParameters;
  62. ParameterCollection updateParameters;
  63. ParameterCollection deleteParameters;
  64. ParameterCollection insertParameters;
  65. ParameterCollection filterParameters;
  66. static readonly object DeletedEvent = new object();
  67. static readonly object DeletingEvent = new object();
  68. static readonly object FilteringEvent = new object();
  69. static readonly object InsertedEvent = new object();
  70. static readonly object InsertingEvent = new object();
  71. static readonly object ObjectCreatedEvent = new object();
  72. static readonly object ObjectCreatingEvent = new object();
  73. static readonly object ObjectDisposingEvent = new object();
  74. // static readonly object ResolvingMethodEvent = new object();
  75. static readonly object SelectedEvent = new object();
  76. static readonly object SelectingEvent = new object();
  77. static readonly object UpdatedEvent = new object();
  78. static readonly object UpdatingEvent = new object();
  79. public ObjectDataSourceView (ObjectDataSource owner, string name, HttpContext context): base (owner, name)
  80. {
  81. this.owner = owner;
  82. this.context = context;
  83. }
  84. public event ObjectDataSourceStatusEventHandler Deleted {
  85. add { Events.AddHandler (DeletedEvent, value); }
  86. remove { Events.RemoveHandler (DeletedEvent, value); }
  87. }
  88. public event ObjectDataSourceMethodEventHandler Deleting {
  89. add { Events.AddHandler (DeletingEvent, value); }
  90. remove { Events.RemoveHandler (DeletingEvent, value); }
  91. }
  92. public event ObjectDataSourceFilteringEventHandler Filtering {
  93. add { Events.AddHandler (FilteringEvent, value); }
  94. remove { Events.RemoveHandler (FilteringEvent, value); }
  95. }
  96. public event ObjectDataSourceStatusEventHandler Inserted {
  97. add { Events.AddHandler (InsertedEvent, value); }
  98. remove { Events.RemoveHandler (InsertedEvent, value); }
  99. }
  100. public event ObjectDataSourceMethodEventHandler Inserting {
  101. add { Events.AddHandler (InsertingEvent, value); }
  102. remove { Events.RemoveHandler (InsertingEvent, value); }
  103. }
  104. public event ObjectDataSourceObjectEventHandler ObjectCreated {
  105. add { Events.AddHandler (ObjectCreatedEvent, value); }
  106. remove { Events.RemoveHandler (ObjectCreatedEvent, value); }
  107. }
  108. public event ObjectDataSourceObjectEventHandler ObjectCreating {
  109. add { Events.AddHandler (ObjectCreatingEvent, value); }
  110. remove { Events.RemoveHandler (ObjectCreatingEvent, value); }
  111. }
  112. public event ObjectDataSourceDisposingEventHandler ObjectDisposing {
  113. add { Events.AddHandler (ObjectDisposingEvent, value); }
  114. remove { Events.RemoveHandler (ObjectDisposingEvent, value); }
  115. }
  116. /* public event ObjectDataSourceResolvingMethodEventHandler ResolvingMethod {
  117. add { Events.AddHandler (ResolvingMethodEvent, value); }
  118. remove { Events.RemoveHandler (ResolvingMethodEvent, value); }
  119. }
  120. */
  121. public event ObjectDataSourceStatusEventHandler Selected {
  122. add { Events.AddHandler (SelectedEvent, value); }
  123. remove { Events.RemoveHandler (SelectedEvent, value); }
  124. }
  125. public event ObjectDataSourceSelectingEventHandler Selecting {
  126. add { Events.AddHandler (SelectingEvent, value); }
  127. remove { Events.RemoveHandler (SelectingEvent, value); }
  128. }
  129. public event ObjectDataSourceStatusEventHandler Updated {
  130. add { Events.AddHandler (UpdatedEvent, value); }
  131. remove { Events.RemoveHandler (UpdatedEvent, value); }
  132. }
  133. public event ObjectDataSourceMethodEventHandler Updating {
  134. add { Events.AddHandler (UpdatingEvent, value); }
  135. remove { Events.RemoveHandler (UpdatingEvent, value); }
  136. }
  137. protected virtual void OnDeleted (ObjectDataSourceStatusEventArgs e)
  138. {
  139. if (Events != null) {
  140. ObjectDataSourceStatusEventHandler eh = (ObjectDataSourceStatusEventHandler) Events [DeletedEvent];
  141. if (eh != null) eh (this, e);
  142. }
  143. }
  144. protected virtual void OnDeleting (ObjectDataSourceMethodEventArgs e)
  145. {
  146. if (Events != null) {
  147. ObjectDataSourceMethodEventHandler eh = (ObjectDataSourceMethodEventHandler) Events [DeletingEvent];
  148. if (eh != null) eh (this, e);
  149. }
  150. }
  151. protected virtual void OnFiltering (ObjectDataSourceFilteringEventArgs e)
  152. {
  153. if (Events != null) {
  154. ObjectDataSourceFilteringEventHandler eh = (ObjectDataSourceFilteringEventHandler) Events [FilteringEvent];
  155. if (eh != null) eh (this, e);
  156. }
  157. }
  158. protected virtual void OnInserted (ObjectDataSourceStatusEventArgs e)
  159. {
  160. if (Events != null) {
  161. ObjectDataSourceStatusEventHandler eh = (ObjectDataSourceStatusEventHandler) Events [InsertedEvent];
  162. if (eh != null) eh (this, e);
  163. }
  164. }
  165. protected virtual void OnInserting (ObjectDataSourceMethodEventArgs e)
  166. {
  167. if (Events != null) {
  168. ObjectDataSourceMethodEventHandler eh = (ObjectDataSourceMethodEventHandler) Events [InsertingEvent];
  169. if (eh != null) eh (this, e);
  170. }
  171. }
  172. protected virtual void OnObjectCreated (ObjectDataSourceEventArgs e)
  173. {
  174. if (Events != null) {
  175. ObjectDataSourceObjectEventHandler eh = (ObjectDataSourceObjectEventHandler) Events [ObjectCreatedEvent];
  176. if (eh != null) eh (this, e);
  177. }
  178. }
  179. protected virtual void OnObjectCreating (ObjectDataSourceEventArgs e)
  180. {
  181. if (Events != null) {
  182. ObjectDataSourceObjectEventHandler eh = (ObjectDataSourceObjectEventHandler) Events [ObjectCreatingEvent];
  183. if (eh != null) eh (this, e);
  184. }
  185. }
  186. protected virtual void OnObjectDisposing (ObjectDataSourceDisposingEventArgs e)
  187. {
  188. if (Events != null) {
  189. ObjectDataSourceDisposingEventHandler eh = (ObjectDataSourceDisposingEventHandler) Events [ObjectDisposingEvent];
  190. if (eh != null) eh (this, e);
  191. }
  192. }
  193. /* protected virtual void OnResolvingMethod (ObjectDataSourceResolvingMethodEventArgs e)
  194. {
  195. if (Events != null) {
  196. ObjectDataSourceResolvingMethodEventHandler eh = (ObjectDataSourceResolvingMethodEventHandler) Events [ResolvingMethodEvent];
  197. if (eh != null) eh (this, e);
  198. }
  199. }
  200. */
  201. protected virtual void OnSelected (ObjectDataSourceStatusEventArgs e)
  202. {
  203. if (Events != null) {
  204. ObjectDataSourceStatusEventHandler eh = (ObjectDataSourceStatusEventHandler) Events [SelectedEvent];
  205. if (eh != null) eh (this, e);
  206. }
  207. }
  208. protected virtual void OnSelecting (ObjectDataSourceSelectingEventArgs e)
  209. {
  210. if (Events != null) {
  211. ObjectDataSourceSelectingEventHandler eh = (ObjectDataSourceSelectingEventHandler) Events [SelectingEvent];
  212. if (eh != null) eh (this, e);
  213. }
  214. }
  215. protected virtual void OnUpdated (ObjectDataSourceStatusEventArgs e)
  216. {
  217. if (Events != null) {
  218. ObjectDataSourceStatusEventHandler eh = (ObjectDataSourceStatusEventHandler) Events [UpdatedEvent];
  219. if (eh != null) eh (this, e);
  220. }
  221. }
  222. protected virtual void OnUpdating (ObjectDataSourceMethodEventArgs e)
  223. {
  224. if (Events != null) {
  225. ObjectDataSourceMethodEventHandler eh = (ObjectDataSourceMethodEventHandler) Events [UpdatingEvent];
  226. if (eh != null) eh (this, e);
  227. }
  228. }
  229. public override bool CanDelete {
  230. get { return DeleteMethod.Length > 0; }
  231. }
  232. public override bool CanInsert {
  233. get { return InsertMethod.Length > 0; }
  234. }
  235. public override bool CanPage {
  236. get { return EnablePaging; }
  237. }
  238. public override bool CanRetrieveTotalRowCount {
  239. get {
  240. if( SelectCountMethod.Length > 0)
  241. return true;
  242. return !EnablePaging;
  243. }
  244. }
  245. public override bool CanSort {
  246. get { return true; }
  247. }
  248. public override bool CanUpdate {
  249. get { return UpdateMethod.Length > 0; }
  250. }
  251. // LAME SPEC: MSDN says value should be stored in ViewState but tests show otherwise.
  252. ConflictOptions conflictDetection = ConflictOptions.OverwriteChanges;
  253. public ConflictOptions ConflictDetection {
  254. get { return conflictDetection; }
  255. set {
  256. if (ConflictDetection == value)
  257. return;
  258. conflictDetection = value;
  259. OnDataSourceViewChanged (EventArgs.Empty);
  260. }
  261. }
  262. public bool ConvertNullToDBNull {
  263. get { return convertNullToDBNull; }
  264. set { convertNullToDBNull = value; }
  265. }
  266. public string DataObjectTypeName {
  267. get {
  268. return dataObjectTypeName != null ? dataObjectTypeName : string.Empty;
  269. }
  270. set {
  271. if (DataObjectTypeName == value)
  272. return;
  273. dataObjectTypeName = value;
  274. dataObjectType = null;
  275. OnDataSourceViewChanged (EventArgs.Empty);
  276. }
  277. }
  278. public string DeleteMethod {
  279. get {
  280. return deleteMethod != null ? deleteMethod : string.Empty;
  281. }
  282. set {
  283. deleteMethod = value;
  284. }
  285. }
  286. public ParameterCollection DeleteParameters {
  287. get {
  288. if (deleteParameters == null) {
  289. deleteParameters = new ParameterCollection ();
  290. }
  291. return deleteParameters;
  292. }
  293. }
  294. public bool EnablePaging {
  295. get {
  296. return enablePaging;
  297. }
  298. set {
  299. if (EnablePaging == value)
  300. return;
  301. enablePaging = value;
  302. OnDataSourceViewChanged (EventArgs.Empty);
  303. }
  304. }
  305. public string FilterExpression {
  306. get {
  307. return filterExpression != null ? filterExpression : string.Empty;
  308. }
  309. set {
  310. if (FilterExpression == value)
  311. return;
  312. filterExpression = value;
  313. OnDataSourceViewChanged (EventArgs.Empty);
  314. }
  315. }
  316. public ParameterCollection FilterParameters {
  317. get {
  318. if (filterParameters == null) {
  319. filterParameters = new ParameterCollection ();
  320. filterParameters.ParametersChanged += new EventHandler (OnParametersChanged);
  321. if (IsTrackingViewState)
  322. ((IStateManager)filterParameters).TrackViewState ();
  323. }
  324. return filterParameters;
  325. }
  326. }
  327. public string InsertMethod {
  328. get {
  329. return insertMethod != null ? insertMethod : string.Empty;
  330. }
  331. set {
  332. insertMethod = value;
  333. }
  334. }
  335. public ParameterCollection InsertParameters {
  336. get {
  337. if (insertParameters == null) {
  338. insertParameters = new ParameterCollection ();
  339. }
  340. return insertParameters;
  341. }
  342. }
  343. public string MaximumRowsParameterName {
  344. get {
  345. return maximumRowsParameterName != null ? maximumRowsParameterName : "maximumRows";
  346. }
  347. set {
  348. if (MaximumRowsParameterName == value)
  349. return;
  350. maximumRowsParameterName = value;
  351. OnDataSourceViewChanged (EventArgs.Empty);
  352. }
  353. }
  354. [DefaultValue ("{0}")]
  355. public string OldValuesParameterFormatString {
  356. get {
  357. return oldValuesParameterFormatString != null ? oldValuesParameterFormatString : "{0}";
  358. }
  359. set {
  360. if (OldValuesParameterFormatString == value)
  361. return;
  362. oldValuesParameterFormatString = value;
  363. OnDataSourceViewChanged (EventArgs.Empty);
  364. }
  365. }
  366. public string SelectCountMethod {
  367. get {
  368. return selectCountMethod != null ? selectCountMethod : string.Empty;
  369. }
  370. set {
  371. if (SelectCountMethod == value)
  372. return;
  373. selectCountMethod = value;
  374. OnDataSourceViewChanged (EventArgs.Empty);
  375. }
  376. }
  377. public string SelectMethod {
  378. get {
  379. return selectMethod != null ? selectMethod : string.Empty;
  380. }
  381. set {
  382. if (SelectMethod == value)
  383. return;
  384. selectMethod = value;
  385. OnDataSourceViewChanged (EventArgs.Empty);
  386. }
  387. }
  388. public ParameterCollection SelectParameters {
  389. get {
  390. if (selectParameters == null) {
  391. selectParameters = new ParameterCollection ();
  392. selectParameters.ParametersChanged += new EventHandler (OnParametersChanged);
  393. if (IsTrackingViewState)
  394. ((IStateManager)selectParameters).TrackViewState ();
  395. }
  396. return selectParameters;
  397. }
  398. }
  399. public string SortParameterName {
  400. get {
  401. return sortParameterName != null ? sortParameterName : string.Empty;
  402. }
  403. set {
  404. sortParameterName = value;
  405. }
  406. }
  407. public string StartRowIndexParameterName {
  408. get {
  409. return startRowIndexParameterName != null ? startRowIndexParameterName : "startRowIndex";
  410. }
  411. set {
  412. if (StartRowIndexParameterName == value)
  413. return;
  414. startRowIndexParameterName = value;
  415. OnDataSourceViewChanged (EventArgs.Empty);
  416. }
  417. }
  418. public string TypeName {
  419. get {
  420. return typeName != null ? typeName : string.Empty;
  421. }
  422. set {
  423. if (TypeName == value)
  424. return;
  425. typeName = value;
  426. objectType = null;
  427. OnDataSourceViewChanged (EventArgs.Empty);
  428. }
  429. }
  430. public string UpdateMethod {
  431. get {
  432. return updateMethod != null ? updateMethod : string.Empty;
  433. }
  434. set {
  435. updateMethod = value;
  436. }
  437. }
  438. public ParameterCollection UpdateParameters {
  439. get {
  440. if (updateParameters == null) {
  441. updateParameters = new ParameterCollection ();
  442. }
  443. return updateParameters;
  444. }
  445. }
  446. Type ObjectType {
  447. get {
  448. if (objectType == null) {
  449. objectType = HttpApplication.LoadType (TypeName);
  450. if (objectType == null)
  451. throw new InvalidOperationException ("Type not found: " + TypeName);
  452. }
  453. return objectType;
  454. }
  455. }
  456. Type DataObjectType {
  457. get {
  458. if (dataObjectType == null) {
  459. dataObjectType = HttpApplication.LoadType (DataObjectTypeName);
  460. if (dataObjectType == null)
  461. throw new InvalidOperationException ("Type not found: " + DataObjectTypeName);
  462. }
  463. return dataObjectType;
  464. }
  465. }
  466. public IEnumerable Select (DataSourceSelectArguments arguments)
  467. {
  468. return ExecuteSelect (arguments);
  469. }
  470. public int Update (IDictionary keys, IDictionary values, IDictionary oldValues)
  471. {
  472. return ExecuteUpdate (keys, values, oldValues);
  473. }
  474. public int Delete (IDictionary keys, IDictionary oldValues)
  475. {
  476. return ExecuteDelete (keys, oldValues);
  477. }
  478. public int Insert (IDictionary values)
  479. {
  480. return ExecuteInsert (values);
  481. }
  482. protected override int ExecuteInsert (IDictionary values)
  483. {
  484. if (!CanInsert)
  485. throw new NotSupportedException ("Insert operation not supported.");
  486. IOrderedDictionary paramValues;
  487. MethodInfo method;
  488. if (DataObjectTypeName.Length == 0) {
  489. paramValues = MergeParameterValues (InsertParameters, values, null);
  490. method = GetObjectMethod (InsertMethod, paramValues, DataObjectMethodType.Insert);
  491. } else {
  492. method = ResolveDataObjectMethod (InsertMethod, values, null, out paramValues);
  493. }
  494. ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
  495. OnInserting (args);
  496. if (args.Cancel)
  497. return -1;
  498. ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
  499. OnInserted (rargs);
  500. if (rargs.Exception != null && !rargs.ExceptionHandled)
  501. throw rargs.Exception;
  502. if (owner.EnableCaching)
  503. owner.Cache.Expire ();
  504. OnDataSourceViewChanged (EventArgs.Empty);
  505. return -1;
  506. }
  507. protected override int ExecuteDelete (IDictionary keys, IDictionary oldValues)
  508. {
  509. if (!CanDelete)
  510. throw new NotSupportedException ("Delete operation not supported.");
  511. if (ConflictDetection == ConflictOptions.CompareAllValues && (oldValues == null || oldValues.Count == 0))
  512. throw new InvalidOperationException ("ConflictDetection is set to CompareAllValues and oldValues collection is null or empty.");
  513. IDictionary oldDataValues;
  514. oldDataValues = BuildOldValuesList (keys, oldValues, false);
  515. IOrderedDictionary paramValues;
  516. MethodInfo method;
  517. if (DataObjectTypeName.Length == 0) {
  518. paramValues = MergeParameterValues (DeleteParameters, null, oldDataValues);
  519. method = GetObjectMethod (DeleteMethod, paramValues, DataObjectMethodType.Delete);
  520. } else {
  521. method = ResolveDataObjectMethod (DeleteMethod, oldDataValues, null, out paramValues);
  522. }
  523. ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
  524. OnDeleting (args);
  525. if (args.Cancel)
  526. return -1;
  527. ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
  528. OnDeleted (rargs);
  529. if (rargs.Exception != null && !rargs.ExceptionHandled)
  530. throw rargs.Exception;
  531. if (owner.EnableCaching)
  532. owner.Cache.Expire ();
  533. OnDataSourceViewChanged (EventArgs.Empty);
  534. return -1;
  535. }
  536. protected override int ExecuteUpdate (IDictionary keys, IDictionary values, IDictionary oldValues)
  537. {
  538. IOrderedDictionary paramValues;
  539. MethodInfo method;
  540. IDictionary oldDataValues;
  541. oldDataValues = BuildOldValuesList (keys, oldValues, true);
  542. if (DataObjectTypeName.Length == 0)
  543. {
  544. IDictionary dataValues;
  545. dataValues = values;
  546. paramValues = MergeParameterValues (UpdateParameters, dataValues, oldDataValues);
  547. method = GetObjectMethod (UpdateMethod, paramValues, DataObjectMethodType.Update);
  548. }
  549. else
  550. {
  551. if (ConflictDetection != ConflictOptions.CompareAllValues) {
  552. oldDataValues = null;
  553. }
  554. IDictionary dataValues = new Hashtable ();
  555. if (keys != null) {
  556. foreach (DictionaryEntry de in keys)
  557. dataValues [de.Key] = de.Value;
  558. }
  559. if (values != null) {
  560. foreach (DictionaryEntry de in values)
  561. dataValues [de.Key] = de.Value;
  562. }
  563. method = ResolveDataObjectMethod (UpdateMethod, dataValues, oldDataValues, out paramValues);
  564. }
  565. ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
  566. OnUpdating (args);
  567. if (args.Cancel)
  568. return -1;
  569. ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
  570. OnUpdated (rargs);
  571. if (rargs.Exception != null && !rargs.ExceptionHandled)
  572. throw rargs.Exception;
  573. if (owner.EnableCaching)
  574. owner.Cache.Expire ();
  575. OnDataSourceViewChanged (EventArgs.Empty);
  576. return -1;
  577. }
  578. IDictionary BuildOldValuesList (IDictionary keys, IDictionary oldValues, bool keysWin)
  579. {
  580. IDictionary oldDataValues;
  581. if (ConflictDetection == ConflictOptions.CompareAllValues) {
  582. oldDataValues = new Hashtable ();
  583. if (keys != null && !keysWin) {
  584. foreach (DictionaryEntry de in keys)
  585. oldDataValues [de.Key] = de.Value;
  586. }
  587. if (oldValues != null) {
  588. foreach (DictionaryEntry de in oldValues)
  589. oldDataValues [de.Key] = de.Value;
  590. }
  591. if (keys != null && keysWin) {
  592. foreach (DictionaryEntry de in keys)
  593. oldDataValues [de.Key] = de.Value;
  594. }
  595. }
  596. else {
  597. oldDataValues = keys;
  598. }
  599. return oldDataValues;
  600. }
  601. protected internal override IEnumerable ExecuteSelect (DataSourceSelectArguments arguments)
  602. {
  603. arguments.RaiseUnsupportedCapabilitiesError (this);
  604. IOrderedDictionary paramValues = MergeParameterValues (SelectParameters, null, null);
  605. ObjectDataSourceSelectingEventArgs args = new ObjectDataSourceSelectingEventArgs (paramValues, arguments, false);
  606. object result = null;
  607. if (owner.EnableCaching)
  608. result = owner.Cache.GetCachedObject (SelectMethod, SelectParameters);
  609. if (result == null) {
  610. OnSelecting (args);
  611. if (args.Cancel)
  612. return new ArrayList ();
  613. if (CanPage) {
  614. if (StartRowIndexParameterName.Length == 0)
  615. throw new InvalidOperationException ("Paging is enabled, but the StartRowIndexParameterName property is not set.");
  616. if (MaximumRowsParameterName.Length == 0)
  617. throw new InvalidOperationException ("Paging is enabled, but the MaximumRowsParameterName property is not set.");
  618. paramValues [StartRowIndexParameterName] = arguments.StartRowIndex;
  619. paramValues [MaximumRowsParameterName] = arguments.MaximumRows;
  620. }
  621. if (SortParameterName.Length > 0)
  622. paramValues [SortParameterName] = arguments.SortExpression;
  623. result = InvokeSelect (SelectMethod, paramValues);
  624. if (CanRetrieveTotalRowCount && arguments.RetrieveTotalRowCount)
  625. arguments.TotalRowCount = QueryTotalRowCount (MergeParameterValues (SelectParameters, null, null), arguments);
  626. if (owner.EnableCaching)
  627. owner.Cache.SetCachedObject (SelectMethod, SelectParameters, result);
  628. }
  629. if (FilterExpression.Length > 0 && !(result is DataGrid || result is DataView || result is DataTable))
  630. throw new NotSupportedException ("The FilterExpression property was set and the Select method does not return a DataSet, DataTable, or DataView.");
  631. if (owner.EnableCaching && result is IDataReader)
  632. throw new NotSupportedException ("Data source does not support caching objects that implement IDataReader");
  633. if (result is DataSet) {
  634. DataSet dset = (DataSet) result;
  635. if (dset.Tables.Count == 0)
  636. throw new InvalidOperationException ("The select method returnet a DataSet which doesn't contain any table.");
  637. result = dset.Tables [0];
  638. }
  639. if (result is DataTable) {
  640. DataView dview = new DataView ((DataTable)result);
  641. if (arguments.SortExpression != null && arguments.SortExpression.Length > 0) {
  642. dview.Sort = arguments.SortExpression;
  643. }
  644. if (FilterExpression.Length > 0) {
  645. IOrderedDictionary fparams = FilterParameters.GetValues (context, owner);
  646. ObjectDataSourceFilteringEventArgs fargs = new ObjectDataSourceFilteringEventArgs (fparams);
  647. OnFiltering (fargs);
  648. if (!fargs.Cancel) {
  649. object[] formatValues = new object [fparams.Count];
  650. for (int n=0; n<formatValues.Length; n++) {
  651. formatValues [n] = fparams [n];
  652. if (formatValues [n] == null) return dview;
  653. }
  654. dview.RowFilter = string.Format (FilterExpression, formatValues);
  655. }
  656. }
  657. return dview;
  658. }
  659. if (result is IEnumerable)
  660. return (IEnumerable) result;
  661. else
  662. return new object[] {result};
  663. }
  664. int QueryTotalRowCount (IOrderedDictionary mergedParameters, DataSourceSelectArguments arguments)
  665. {
  666. ObjectDataSourceSelectingEventArgs countArgs = new ObjectDataSourceSelectingEventArgs (mergedParameters, arguments, true);
  667. OnSelecting (countArgs);
  668. if (countArgs.Cancel)
  669. return 0;
  670. object count = InvokeSelect (SelectCountMethod, mergedParameters);
  671. return (int) Convert.ChangeType (count, typeof(int));
  672. }
  673. object InvokeSelect (string methodName, IOrderedDictionary paramValues)
  674. {
  675. MethodInfo method = GetObjectMethod (methodName, paramValues, DataObjectMethodType.Select);
  676. ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
  677. OnSelected (rargs);
  678. if (rargs.Exception != null && !rargs.ExceptionHandled)
  679. throw rargs.Exception;
  680. return rargs.ReturnValue;
  681. }
  682. ObjectDataSourceStatusEventArgs InvokeMethod (MethodInfo method, IOrderedDictionary paramValues)
  683. {
  684. object instance = null;
  685. if (!method.IsStatic)
  686. instance = CreateObjectInstance ();
  687. ParameterInfo[] pars = method.GetParameters ();
  688. ArrayList outParamInfos;
  689. object[] methodArgs = GetParameterArray (pars, paramValues, out outParamInfos);
  690. if (methodArgs == null)
  691. throw CreateMethodException (method.Name, paramValues);
  692. object result = null;
  693. Hashtable outParams = null;
  694. try {
  695. result = method.Invoke (instance, methodArgs);
  696. if (outParamInfos != null) {
  697. outParams = new Hashtable ();
  698. foreach (ParameterInfo op in outParamInfos)
  699. outParams [op.Name] = methodArgs [op.Position];
  700. }
  701. return new ObjectDataSourceStatusEventArgs (result, outParams, null);
  702. }
  703. catch (Exception ex) {
  704. return new ObjectDataSourceStatusEventArgs (result, outParams, ex);
  705. }
  706. finally {
  707. if (instance != null)
  708. DisposeObjectInstance (instance);
  709. }
  710. }
  711. MethodInfo GetObjectMethod (string methodName, IOrderedDictionary parameters, DataObjectMethodType methodType)
  712. {
  713. MemberInfo[] methods = ObjectType.GetMember (methodName, MemberTypes.Method, BindingFlags.Instance |
  714. BindingFlags.Static |
  715. BindingFlags.Public |
  716. BindingFlags.IgnoreCase |
  717. BindingFlags.FlattenHierarchy);
  718. if (methods.Length > 1) {
  719. // MSDN: The ObjectDataSource resolves method overloads by method name and number
  720. // of parameters; the names and types of the parameters are not considered.
  721. // LAMESPEC: the tests show otherwise
  722. DataObjectMethodAttribute methodAttribute = null;
  723. MethodInfo methodInfo = null;
  724. bool hasConflict = false;
  725. foreach (MethodInfo me in methods) { // we look for methods only
  726. ParameterInfo [] pinfos = me.GetParameters ();
  727. if (pinfos.Length == parameters.Count) {
  728. object [] attrs = me.GetCustomAttributes (typeof (DataObjectMethodAttribute), true);
  729. DataObjectMethodAttribute domAttr = (attrs != null && attrs.Length > 0) ? (DataObjectMethodAttribute) attrs [0] : null;
  730. if (domAttr != null && domAttr.MethodType != methodType)
  731. continue;
  732. bool paramsMatch = true;
  733. foreach (ParameterInfo pinfo in pinfos) {
  734. if (!parameters.Contains (pinfo.Name)) {
  735. paramsMatch = false;
  736. break;
  737. }
  738. }
  739. if (!paramsMatch)
  740. continue;
  741. if (domAttr != null) {
  742. if (methodAttribute != null) {
  743. if (methodAttribute.IsDefault) {
  744. if (domAttr.IsDefault) {
  745. methodInfo = null;
  746. break; //fail due to a conflict
  747. }
  748. else
  749. continue; //existing matches better
  750. }
  751. else {
  752. methodInfo = null; //we override
  753. hasConflict = !domAttr.IsDefault;
  754. }
  755. }
  756. else
  757. methodInfo = null; //we override
  758. }
  759. if (methodInfo == null) {
  760. methodAttribute = domAttr;
  761. methodInfo = me;
  762. continue;
  763. }
  764. hasConflict = true;
  765. }
  766. }
  767. if (!hasConflict && methodInfo != null)
  768. return methodInfo;
  769. }
  770. else if (methods.Length == 1) {
  771. MethodInfo me = methods[0] as MethodInfo;
  772. if (me != null && me.GetParameters().Length == parameters.Count)
  773. return me;
  774. }
  775. throw CreateMethodException (methodName, parameters);
  776. }
  777. MethodInfo ResolveDataObjectMethod (string methodName, IDictionary values, IDictionary oldValues, out IOrderedDictionary paramValues)
  778. {
  779. MethodInfo method;
  780. if (oldValues != null)
  781. method = ObjectType.GetMethod (methodName, new Type[] { DataObjectType, DataObjectType });
  782. else
  783. method = ObjectType.GetMethod (methodName, new Type[] { DataObjectType });
  784. if (method == null)
  785. throw new InvalidOperationException ("ObjectDataSource " + owner.ID + " could not find a method named '" + methodName + "' with parameters of type '" + DataObjectType + "' in '" + ObjectType + "'.");
  786. paramValues = new OrderedDictionary (StringComparer.InvariantCultureIgnoreCase);
  787. ParameterInfo[] ps = method.GetParameters ();
  788. if (oldValues != null) {
  789. if (FormatOldParameter (ps[0].Name) == ps[1].Name) {
  790. paramValues [ps[0].Name] = CreateDataObject (values);
  791. paramValues [ps[1].Name] = CreateDataObject (oldValues);
  792. } else if (FormatOldParameter (ps[1].Name) == ps[0].Name) {
  793. paramValues [ps[0].Name] = CreateDataObject (oldValues);
  794. paramValues [ps[1].Name] = CreateDataObject (values);
  795. } else
  796. throw new InvalidOperationException ("Method '" + methodName + "' does not have any parameter that fits the value of OldValuesParameterFormatString.");
  797. } else {
  798. paramValues [ps[0].Name] = CreateDataObject (values);
  799. }
  800. return method;
  801. }
  802. Exception CreateMethodException (string methodName, IOrderedDictionary parameters)
  803. {
  804. string s = "";
  805. foreach (string p in parameters.Keys) {
  806. s += p + ", ";
  807. }
  808. return new InvalidOperationException ("ObjectDataSource " + owner.ID + " could not find a method named '" + methodName + "' with parameters " + s + "in type '" + ObjectType + "'.");
  809. }
  810. object CreateDataObject (IDictionary values)
  811. {
  812. object ob = Activator.CreateInstance (DataObjectType);
  813. foreach (DictionaryEntry de in values) {
  814. PropertyInfo p = DataObjectType.GetProperty ((string)de.Key);
  815. if (p == null) throw new InvalidOperationException ("Property " + de.Key + " not found in type '" +DataObjectType + "'.");
  816. object[] attributes = p.GetCustomAttributes (typeof (System.ComponentModel.TypeConverterAttribute),
  817. true);
  818. Type propertyType = p.PropertyType;
  819. object value = de.Value;
  820. object converted = ConvertParameterWithTypeConverter (attributes, propertyType, value);
  821. if (converted == null)
  822. converted = ConvertParameter (propertyType, value);
  823. p.SetValue (ob, converted, null);
  824. }
  825. return ob;
  826. }
  827. object CreateObjectInstance ()
  828. {
  829. ObjectDataSourceEventArgs args = new ObjectDataSourceEventArgs (null);
  830. OnObjectCreating (args);
  831. if (args.ObjectInstance != null)
  832. return args.ObjectInstance;
  833. object ob = Activator.CreateInstance (ObjectType);
  834. args.ObjectInstance = ob;
  835. OnObjectCreated (args);
  836. return args.ObjectInstance;
  837. }
  838. void DisposeObjectInstance (object obj)
  839. {
  840. ObjectDataSourceDisposingEventArgs args = new ObjectDataSourceDisposingEventArgs (obj);
  841. OnObjectDisposing (args);
  842. if (!args.Cancel) {
  843. IDisposable disp = obj as IDisposable;
  844. if (disp != null) disp.Dispose ();
  845. }
  846. }
  847. object FindValueByName (string name, IDictionary values, bool format)
  848. {
  849. if (values == null)
  850. return null;
  851. foreach (DictionaryEntry de in values) {
  852. string valueName = format == true ? FormatOldParameter (de.Key.ToString ()) : de.Key.ToString ();
  853. if (String.Compare (name, valueName, StringComparison.InvariantCultureIgnoreCase) == 0)
  854. return values [de.Key];
  855. }
  856. return null;
  857. }
  858. /// <summary>
  859. /// Merge the current data item fields with view parameter default values
  860. /// </summary>
  861. /// <param name="viewParams">default parameters</param>
  862. /// <param name="values">new parameters for update and insert</param>
  863. /// <param name="oldValues">old parameters for update and delete</param>
  864. /// <param name="allwaysAddNewValues">true for insert, as current item is
  865. /// irrelevant for insert</param>
  866. /// <returns>merged values</returns>
  867. IOrderedDictionary MergeParameterValues (ParameterCollection viewParams, IDictionary values, IDictionary oldValues)
  868. {
  869. IOrderedDictionary parametersValues = viewParams.GetValues (context, owner);
  870. OrderedDictionary mergedValues = new OrderedDictionary (StringComparer.InvariantCultureIgnoreCase);
  871. foreach (string parameterName in parametersValues.Keys) {
  872. mergedValues [parameterName] = parametersValues [parameterName];
  873. if (oldValues != null) {
  874. object value = FindValueByName (parameterName, oldValues, true);
  875. if (value != null) {
  876. object dataValue = viewParams [parameterName].ConvertValue (value);
  877. mergedValues [parameterName] = dataValue;
  878. }
  879. }
  880. if (values != null) {
  881. object value = FindValueByName (parameterName, values, false);
  882. if (value != null) {
  883. object dataValue = viewParams [parameterName].ConvertValue (value);
  884. mergedValues [parameterName] = dataValue;
  885. }
  886. }
  887. }
  888. if (values != null) {
  889. foreach (DictionaryEntry de in values)
  890. if (FindValueByName ((string) de.Key, mergedValues, false) == null)
  891. mergedValues [de.Key] = de.Value;
  892. }
  893. if (oldValues != null) {
  894. foreach (DictionaryEntry de in oldValues) {
  895. string oldValueKey = FormatOldParameter ((string) de.Key);
  896. if (FindValueByName (oldValueKey, mergedValues, false) == null)
  897. mergedValues [oldValueKey] = de.Value;
  898. }
  899. }
  900. return mergedValues;
  901. }
  902. object[] GetParameterArray (ParameterInfo[] methodParams, IOrderedDictionary viewParams, out ArrayList outParamInfos)
  903. {
  904. // FIXME: make this case insensitive
  905. outParamInfos = null;
  906. object[] values = new object [methodParams.Length];
  907. foreach (ParameterInfo mp in methodParams) {
  908. // Parameter names must match
  909. if (!viewParams.Contains (mp.Name)) return null;
  910. values [mp.Position] = ConvertParameter (mp.ParameterType, viewParams [mp.Name]);
  911. if (mp.ParameterType.IsByRef) {
  912. if (outParamInfos == null) outParamInfos = new ArrayList ();
  913. outParamInfos.Add (mp);
  914. }
  915. }
  916. return values;
  917. }
  918. object ConvertParameterWithTypeConverter (object[] attributes, Type targetType, object value)
  919. {
  920. if (attributes == null || attributes.Length == 0 || value == null)
  921. return null;
  922. TypeConverterAttribute tca;
  923. Type converterType;
  924. TypeConverter converter;
  925. foreach (object a in attributes) {
  926. tca = a as TypeConverterAttribute;
  927. if (tca == null)
  928. continue;
  929. converterType = HttpApplication.LoadType (tca.ConverterTypeName, false);
  930. if (converterType == null)
  931. continue;
  932. converter = Activator.CreateInstance (converterType, new object[] {targetType}) as TypeConverter;
  933. if (converter == null)
  934. continue;
  935. if (converter.CanConvertFrom (value.GetType ()))
  936. return converter.ConvertFrom (value);
  937. else if (converter.CanConvertFrom (typeof (string)))
  938. return converter.ConvertFrom (value.ToString ());
  939. }
  940. return null;
  941. }
  942. object ConvertParameter (Type targetType, object value)
  943. {
  944. return ConvertParameter (Type.GetTypeCode (targetType), value);
  945. }
  946. object ConvertParameter (TypeCode targetType, object value)
  947. {
  948. if (value == null) {
  949. if (targetType != TypeCode.Object && targetType != TypeCode.String)
  950. value = 0;
  951. else if (ConvertNullToDBNull)
  952. return DBNull.Value;
  953. }
  954. if (targetType == TypeCode.Object || targetType == TypeCode.Empty)
  955. return value;
  956. else
  957. return Convert.ChangeType (value, targetType);
  958. }
  959. string FormatOldParameter (string name)
  960. {
  961. string f = OldValuesParameterFormatString;
  962. if (f.Length > 0)
  963. return String.Format (f, name);
  964. else
  965. return name;
  966. }
  967. void OnParametersChanged (object sender, EventArgs args)
  968. {
  969. OnDataSourceViewChanged (EventArgs.Empty);
  970. }
  971. protected virtual void LoadViewState (object savedState)
  972. {
  973. object[] state = (savedState == null) ? new object [5] : (object[]) savedState;
  974. ((IStateManager)SelectParameters).LoadViewState (state[0]);
  975. ((IStateManager)UpdateParameters).LoadViewState (state[1]);
  976. ((IStateManager)DeleteParameters).LoadViewState (state[2]);
  977. ((IStateManager)InsertParameters).LoadViewState (state[3]);
  978. ((IStateManager)FilterParameters).LoadViewState (state[4]);
  979. }
  980. protected virtual object SaveViewState()
  981. {
  982. object[] state = new object [5];
  983. if (selectParameters != null)
  984. state [0] = ((IStateManager)selectParameters).SaveViewState ();
  985. if (updateParameters != null)
  986. state [1] = ((IStateManager)updateParameters).SaveViewState ();
  987. if (deleteParameters != null)
  988. state [2] = ((IStateManager)deleteParameters).SaveViewState ();
  989. if (insertParameters != null)
  990. state [3] = ((IStateManager)insertParameters).SaveViewState ();
  991. if (filterParameters != null)
  992. state [4] = ((IStateManager)filterParameters).SaveViewState ();
  993. foreach (object ob in state)
  994. if (ob != null) return state;
  995. return null;
  996. }
  997. protected virtual void TrackViewState()
  998. {
  999. isTrackingViewState = true;
  1000. if (selectParameters != null) ((IStateManager)selectParameters).TrackViewState ();
  1001. if (filterParameters != null) ((IStateManager)filterParameters).TrackViewState ();
  1002. }
  1003. protected bool IsTrackingViewState
  1004. {
  1005. get { return isTrackingViewState; }
  1006. }
  1007. bool IStateManager.IsTrackingViewState
  1008. {
  1009. get { return IsTrackingViewState; }
  1010. }
  1011. void IStateManager.TrackViewState()
  1012. {
  1013. TrackViewState ();
  1014. }
  1015. void IStateManager.LoadViewState (object savedState)
  1016. {
  1017. LoadViewState (savedState);
  1018. }
  1019. object IStateManager.SaveViewState()
  1020. {
  1021. return SaveViewState ();
  1022. }
  1023. }
  1024. }
  1025. #endif