CSLA.NET 5.4.2
CSLA .NET is a software development framework that helps you build a reusable, maintainable object-oriented business layer for your app.
Csla/BusinessBase.cs
Go to the documentation of this file.
1//-----------------------------------------------------------------------
2// <copyright file="BusinessBase.cs" company="Marimer LLC">
3// Copyright (c) Marimer LLC. All rights reserved.
4// Website: https://cslanet.com
5// </copyright>
6// <summary>This is the base class from which most business objects</summary>
7//-----------------------------------------------------------------------
8using System;
9using System.ComponentModel;
10using System.Linq.Expressions;
11using System.Reflection;
12using Csla.Properties;
13using Csla.Core;
14using Csla.Reflection;
15using System.Threading.Tasks;
16
17namespace Csla
18{
19
36 public abstract class BusinessBase<T> :
37 Core.BusinessBase, Core.ISavable, Core.ISavable<T>, IBusinessBase where T : BusinessBase<T>
38 {
39
40 #region Object ID Value
41
46 protected virtual object GetIdValue()
47 {
48 return null;
49 }
50
51 #endregion
52
53 #region System.Object Overrides
54
60 public override string ToString()
61 {
62 object id = GetIdValue();
63 if (id == null)
64 return base.ToString();
65 else
66 return id.ToString();
67 }
68
69 #endregion
70
71 #region Clone
72
79 public T Clone()
80 {
81 return (T)GetClone();
82 }
83
84 #endregion
85
86 #region Data Access
87
121 public T Save()
122 {
123 try
124 {
125 return SaveAsync(false, null, true).Result;
126 }
127 catch (AggregateException ex)
128 {
129 if (ex.InnerExceptions.Count > 0)
130 throw ex.InnerExceptions[0];
131 else
132 throw;
133 }
134 }
135
139 public async Task<T> SaveAsync()
140 {
141 return await SaveAsync(false);
142 }
143
151 public async Task<T> SaveAsync(bool forceUpdate)
152 {
153 return await SaveAsync(forceUpdate, null, false);
154 }
155
165 protected async virtual Task<T> SaveAsync(bool forceUpdate, object userState, bool isSync)
166 {
167 if (forceUpdate && IsNew)
168 {
169 // mark the object as old - which makes it
170 // not dirty
171 MarkOld();
172 // now mark the object as dirty so it can save
173 MarkDirty(true);
174 }
175 T result = default(T);
176 if (this.IsChild)
177 throw new InvalidOperationException(Resources.NoSaveChildException);
178 if (EditLevel > 0)
179 throw new InvalidOperationException(Resources.NoSaveEditingException);
180 if (!IsValid && !IsDeleted)
181 throw new Rules.ValidationException(Resources.NoSaveInvalidException);
182 if (IsBusy)
183 throw new InvalidOperationException(Resources.BusyObjectsMayNotBeSaved);
184 if (IsDirty)
185 {
186 if (isSync)
187 {
188 result = DataPortal.Update<T>((T)this);
189 }
190 else
191 {
192 if (ApplicationContext.AutoCloneOnUpdate)
193 MarkBusy();
194 try
195 {
196 result = await DataPortal.UpdateAsync<T>((T)this);
197 }
198 finally
199 {
200 if (ApplicationContext.AutoCloneOnUpdate)
201 {
202 if (result != null)
203 result.MarkIdle();
204 MarkIdle();
205 }
206 }
207 }
208 }
209 else
210 {
211 result = (T)this;
212 }
213 OnSaved(result, null, userState);
214 return result;
215 }
216
231 public T Save(bool forceUpdate)
232 {
233 if (forceUpdate && IsNew)
234 {
235 // mark the object as old - which makes it
236 // not dirty
237 MarkOld();
238 // now mark the object as dirty so it can save
239 MarkDirty(true);
240 }
241 return this.Save();
242 }
243
249 public async Task SaveAndMergeAsync()
250 {
251 await SaveAndMergeAsync(false);
252 }
253
263 public async Task SaveAndMergeAsync(bool forceUpdate)
264 {
265 new GraphMerger().MergeGraph(this, await SaveAsync(forceUpdate));
266 }
267
271 [Obsolete]
272 public void BeginSave()
273 {
274 BeginSave(null);
275 }
276
281 [Obsolete]
282 public void BeginSave(object userState)
283 {
284 BeginSave(false, null, userState);
285 }
286
293 [Obsolete]
294 public void BeginSave(EventHandler<SavedEventArgs> handler)
295 {
296 BeginSave(false, handler, null);
297 }
298
310 [Obsolete]
311 public async void BeginSave(bool forceUpdate, EventHandler<SavedEventArgs> handler, object userState)
312 {
313 T result = default(T);
314 Exception error = null;
315 try
316 {
317 result = await SaveAsync(forceUpdate, userState, false);
318 }
319 catch (AggregateException ex)
320 {
321 if (ex.InnerExceptions.Count > 0)
322 error = ex.InnerExceptions[0];
323 else
324 error = ex;
325 }
326 catch (Exception ex)
327 {
328 error = ex;
329 }
330
331 if (error != null)
332 OnSaved(null, error, userState);
333 handler?.Invoke(this, new SavedEventArgs(result, error, userState));
334 }
335
348 [Obsolete]
349 public void BeginSave(bool forceUpdate)
350 {
351 this.BeginSave(forceUpdate, null);
352 }
353
370 [Obsolete]
371 public void BeginSave(bool forceUpdate, EventHandler<SavedEventArgs> handler)
372 {
373 this.BeginSave(forceUpdate, handler, null);
374 }
375
390 [Obsolete]
391 public void BeginSave(EventHandler<SavedEventArgs> handler, object userState)
392 {
393 this.BeginSave(false, handler, userState);
394 }
395
396 #endregion
397
398 #region ISavable Members
399
400 void Csla.Core.ISavable.SaveComplete(object newObject)
401 {
402 OnSaved((T)newObject, null, null);
403 }
404
405 void Csla.Core.ISavable<T>.SaveComplete(T newObject)
406 {
407 OnSaved(newObject, null, null);
408 }
409
410 object Csla.Core.ISavable.Save()
411 {
412 return Save();
413 }
414
415 object Csla.Core.ISavable.Save(bool forceUpdate)
416 {
417 return Save(forceUpdate);
418 }
419
420 [NonSerialized]
421 [NotUndoable]
422 private EventHandler<Csla.Core.SavedEventArgs> _nonSerializableSavedHandlers;
423 [NotUndoable]
424 private EventHandler<Csla.Core.SavedEventArgs> _serializableSavedHandlers;
425
429 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
430 "CA1062:ValidateArgumentsOfPublicMethods")]
431 public event EventHandler<Csla.Core.SavedEventArgs> Saved
432 {
433 add
434 {
435 if (value.Method.IsPublic &&
436 (value.Method.DeclaringType.IsSerializable ||
437 value.Method.IsStatic))
438 _serializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
439 System.Delegate.Combine(_serializableSavedHandlers, value);
440 else
441 _nonSerializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
442 System.Delegate.Combine(_nonSerializableSavedHandlers, value);
443 }
444 remove
445 {
446 if (value.Method.IsPublic &&
447 (value.Method.DeclaringType.IsSerializable ||
448 value.Method.IsStatic))
449 _serializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
450 System.Delegate.Remove(_serializableSavedHandlers, value);
451 else
452 _nonSerializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
453 System.Delegate.Remove(_nonSerializableSavedHandlers, value);
454 }
455 }
456
457 async Task<object> ISavable.SaveAsync()
458 {
459 return await SaveAsync();
460 }
461
462 async Task<object> ISavable.SaveAsync(bool forceUpdate)
463 {
464 return await SaveAsync(forceUpdate);
465 }
466
475 [EditorBrowsable(EditorBrowsableState.Advanced)]
476 protected virtual void OnSaved(T newObject, Exception e, object userState)
477 {
478 Csla.Core.SavedEventArgs args = new Csla.Core.SavedEventArgs(newObject, e, userState);
479 if (_nonSerializableSavedHandlers != null)
480 _nonSerializableSavedHandlers.Invoke(this, args);
481 if (_serializableSavedHandlers != null)
482 _serializableSavedHandlers.Invoke(this, args);
483 }
484
485 #endregion
486
487 #region Register Properties/Methods
488
503 {
504 return Core.FieldManager.PropertyInfoManager.RegisterProperty<P>(typeof(T), info);
505 }
506
514 protected static PropertyInfo<P> RegisterProperty<P>(string propertyName)
515 {
516 return RegisterProperty(Csla.Core.FieldManager.PropertyInfoFactory.Factory.Create<P>(typeof(T), propertyName));
517 }
518
526 protected static PropertyInfo<P> RegisterProperty<P>(Expression<Func<T, object>> propertyLambdaExpression)
527 {
528 PropertyInfo reflectedPropertyInfo = Reflect<T>.GetProperty(propertyLambdaExpression);
529 return RegisterProperty<P>(reflectedPropertyInfo.Name);
530 }
531
540 [Obsolete]
541 protected static PropertyInfo<P> RegisterProperty<P>(Expression<Func<T, object>> propertyLambdaExpression, P defaultValue)
542 {
543 PropertyInfo reflectedPropertyInfo = Reflect<T>.GetProperty(propertyLambdaExpression);
544
545 return RegisterProperty(Csla.Core.FieldManager.PropertyInfoFactory.Factory.Create<P>(typeof(T), reflectedPropertyInfo.Name, string.Empty, defaultValue));
546 }
547
556 protected static PropertyInfo<P> RegisterProperty<P>(string propertyName, RelationshipTypes relationship)
557 {
558 return RegisterProperty(Csla.Core.FieldManager.PropertyInfoFactory.Factory.Create<P>(typeof(T), propertyName, string.Empty, relationship));
559 }
560
569 protected static PropertyInfo<P> RegisterProperty<P>(Expression<Func<T, object>> propertyLambdaExpression, RelationshipTypes relationship)
570 {
571 PropertyInfo reflectedPropertyInfo = Reflect<T>.GetProperty(propertyLambdaExpression);
572 return RegisterProperty<P>(reflectedPropertyInfo.Name, relationship);
573 }
574
583 protected static PropertyInfo<P> RegisterProperty<P>(string propertyName, string friendlyName)
584 {
585 return RegisterProperty(Csla.Core.FieldManager.PropertyInfoFactory.Factory.Create<P>(typeof(T), propertyName, friendlyName));
586 }
587
596 protected static PropertyInfo<P> RegisterProperty<P>(Expression<Func<T, object>> propertyLambdaExpression, string friendlyName)
597 {
598 PropertyInfo reflectedPropertyInfo = Reflect<T>.GetProperty(propertyLambdaExpression);
599 return RegisterProperty<P>(reflectedPropertyInfo.Name, friendlyName);
600 }
601
611 [Obsolete]
612 protected static PropertyInfo<P> RegisterProperty<P>(Expression<Func<T, object>> propertyLambdaExpression, string friendlyName, RelationshipTypes relationship)
613 {
614 PropertyInfo reflectedPropertyInfo = Reflect<T>.GetProperty(propertyLambdaExpression);
615
616 return RegisterProperty(Csla.Core.FieldManager.PropertyInfoFactory.Factory.Create<P>(typeof(T), reflectedPropertyInfo.Name, friendlyName, relationship));
617 }
618
628 protected static PropertyInfo<P> RegisterProperty<P>(string propertyName, string friendlyName, P defaultValue)
629 {
630 return RegisterProperty(Csla.Core.FieldManager.PropertyInfoFactory.Factory.Create<P>(typeof(T), propertyName, friendlyName, defaultValue));
631 }
632
642 protected static PropertyInfo<P> RegisterProperty<P>(Expression<Func<T, object>> propertyLambdaExpression, string friendlyName, P defaultValue)
643 {
644 PropertyInfo reflectedPropertyInfo = Reflect<T>.GetProperty(propertyLambdaExpression);
645 return RegisterProperty(reflectedPropertyInfo.Name, friendlyName, defaultValue);
646 }
647
658 protected static PropertyInfo<P> RegisterProperty<P>(string propertyName, string friendlyName, P defaultValue, RelationshipTypes relationship)
659 {
660 return RegisterProperty(Csla.Core.FieldManager.PropertyInfoFactory.Factory.Create<P>(typeof(T), propertyName, friendlyName, defaultValue, relationship));
661 }
662
673 protected static PropertyInfo<P> RegisterProperty<P>(Expression<Func<T, object>> propertyLambdaExpression, string friendlyName, P defaultValue, RelationshipTypes relationship)
674 {
675 PropertyInfo reflectedPropertyInfo = Reflect<T>.GetProperty(propertyLambdaExpression);
676 return RegisterProperty(reflectedPropertyInfo.Name, friendlyName, defaultValue, relationship);
677 }
678
684 protected static MethodInfo RegisterMethod(string methodName)
685 {
686 return RegisterMethod(typeof(T), methodName);
687 }
688
694 protected static MethodInfo RegisterMethod(Expression<Action<T>> methodLambdaExpression)
695 {
696 System.Reflection.MethodInfo reflectedMethodInfo = Reflect<T>.GetMethod(methodLambdaExpression);
697 return RegisterMethod(reflectedMethodInfo.Name);
698 }
699
700 #endregion
701 }
702}
This is the base class from which most business objects will be derived.
void BeginSave(bool forceUpdate, EventHandler< SavedEventArgs > handler)
Starts an async operation to save the object to the database.
T Save(bool forceUpdate)
Saves the object to the database, forcing IsNew to false and IsDirty to True.
async Task< T > SaveAsync(bool forceUpdate)
Saves the object to the database.
static MethodInfo RegisterMethod(string methodName)
Registers a method for use in Authorization.
void BeginSave(object userState)
Starts an async operation to save the object to the database.
EventHandler< Csla.Core.SavedEventArgs > Saved
Event raised when an object has been saved.
static PropertyInfo< P > RegisterProperty< P >(PropertyInfo< P > info)
Indicates that the specified property belongs to the business object type.
static MethodInfo RegisterMethod(Expression< Action< T > > methodLambdaExpression)
Registers a method for use in Authorization.
void BeginSave(EventHandler< SavedEventArgs > handler)
Starts an async operation to save the object to the database.
override string ToString()
Returns a text representation of this object by returning the GetIdValue value in text form.
virtual object GetIdValue()
Override this method to return a unique identifying value for this object.
virtual async Task< T > SaveAsync(bool forceUpdate, object userState, bool isSync)
Saves the object to the database.
T Save()
Saves the object to the database.
T Clone()
Creates a clone of the object.
async Task< T > SaveAsync()
Saves the object to the database.
async Task SaveAndMergeAsync(bool forceUpdate)
Saves the object to the database, merging any resulting updates into the existing object graph.
virtual void OnSaved(T newObject, Exception e, object userState)
Raises the Saved event, indicating that the object has been saved, and providing a reference to the n...
async void BeginSave(bool forceUpdate, EventHandler< SavedEventArgs > handler, object userState)
Starts an async operation to save the object to the database.
void BeginSave(bool forceUpdate)
Starts an async operation to save the object to the database.
void BeginSave()
Starts an async operation to save the object to the database.
void BeginSave(EventHandler< SavedEventArgs > handler, object userState)
Saves the object to the database, forcing IsNew to false and IsDirty to True.
async Task SaveAndMergeAsync()
Saves the object to the database, merging any resulting updates into the existing object graph.
virtual bool IsBusy
Gets a value indicating if this object or its child objects are busy.
virtual bool IsValid
Returns true if the object and its child objects are currently valid, false if the object or any of i...
bool IsDeleted
Returns true if this object is marked for deletion.
virtual object GetClone()
Creates a clone of the object.
bool IsNew
Returns true if this is a new object, false if it is a pre-existing object.
virtual void MarkOld()
Marks the object as being an old (not new) object.
void MarkDirty()
Marks an object as being dirty, or changed.
bool IsChild
Returns true if this is a child (non-root) object.
virtual bool IsDirty
Returns true if this object's data, or any of its fields or child objects data, has been changed.
void MarkIdle()
Mark the object as not busy (it is not running an async operation).
void MarkBusy()
Mark the object as busy (it is running an async operation).
Implements behavior to merge one object graph into a clone of itself (typically post-serialization).
Definition: GraphMerger.cs:20
void MergeGraph(IEditableBusinessObject target, IEditableBusinessObject source)
Merges state from source graph into target graph.
Definition: GraphMerger.cs:26
Event arguments containing a reference to the new object that was returned as a result of the Save() ...
This is the client-side DataPortal.
Definition: DataPortalT.cs:24
T Update(T obj)
Called by a factory method in a business class or by the UI to update an object.
Definition: DataPortalT.cs:715
async Task< T > UpdateAsync(T obj)
Called by a factory method in a business class or by the UI to update an object.
Definition: DataPortalT.cs:773
Maintains metadata about a method.
Definition: MethodInfo.cs:19
MethodInfo(string name)
Creates an instance of the object.
Definition: MethodInfo.cs:24
A strongly-typed resource class, for looking up localized strings, etc.
static string BusyObjectsMayNotBeSaved
Looks up a localized string similar to Objects that are marked busy may not be saved.
static string NoSaveEditingException
Looks up a localized string similar to Object is still being edited and can not be saved.
static string NoSaveInvalidException
Looks up a localized string similar to Object is not valid and can not be saved.
static string NoSaveChildException
Looks up a localized string similar to Can not directly save a child object.
Maintains metadata about a property.
string Name
Gets the property name value.
Specifies that the object can save itself.
Definition: ISavableT.cs:19
void SaveComplete(object newObject)
INTERNAL CSLA .NET USE ONLY.
object Save()
Saves the object to the database.
Task< object > SaveAsync()
Saves the object to the database.
int EditLevel
Gets the current edit level of the object.
Consolidated interface of public elements from the BusinessBase type.
RelationshipTypes
List of valid relationship types between a parent object and another object through a managed propert...
@ Serializable
Prevents updating or inserting until the transaction is complete.