CSLA.NET 6.0.0
CSLA .NET is a software development framework that helps you build a reusable, maintainable object-oriented business layer for your app.
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;
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 {
187 if (isSync)
188 {
189 result = dp.Update((T)this);
190 }
191 else
192 {
194 MarkBusy();
195 try
196 {
197 result = await dp.UpdateAsync((T)this);
198 }
199 finally
200 {
202 {
203 if (result != null)
204 result.MarkIdle();
205 MarkIdle();
206 }
207 }
208 }
209 }
210 else
211 {
212 result = (T)this;
213 }
214 OnSaved(result, null, userState);
215 return result;
216 }
217
232 public T Save(bool forceUpdate)
233 {
234 if (forceUpdate && IsNew)
235 {
236 // mark the object as old - which makes it
237 // not dirty
238 MarkOld();
239 // now mark the object as dirty so it can save
240 MarkDirty(true);
241 }
242 return this.Save();
243 }
244
250 public async Task SaveAndMergeAsync()
251 {
252 await SaveAndMergeAsync(false);
253 }
254
264 public async Task SaveAndMergeAsync(bool forceUpdate)
265 {
266 new GraphMerger(ApplicationContext).MergeGraph(this, await SaveAsync(forceUpdate));
267 }
268
269 #endregion
270
271 #region ISavable Members
272
273 void Csla.Core.ISavable.SaveComplete(object newObject)
274 {
275 OnSaved((T)newObject, null, null);
276 }
277
278 void Csla.Core.ISavable<T>.SaveComplete(T newObject)
279 {
280 OnSaved(newObject, null, null);
281 }
282
283 object Csla.Core.ISavable.Save()
284 {
285 return Save();
286 }
287
288 object Csla.Core.ISavable.Save(bool forceUpdate)
289 {
290 return Save(forceUpdate);
291 }
292
293 [NonSerialized]
294 [NotUndoable]
295 private EventHandler<Csla.Core.SavedEventArgs> _nonSerializableSavedHandlers;
296 [NotUndoable]
297 private EventHandler<Csla.Core.SavedEventArgs> _serializableSavedHandlers;
298
302 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design",
303 "CA1062:ValidateArgumentsOfPublicMethods")]
304 public event EventHandler<Csla.Core.SavedEventArgs> Saved
305 {
306 add
307 {
308 if (value.Method.IsPublic &&
309 (value.Method.DeclaringType.IsSerializable ||
310 value.Method.IsStatic))
311 _serializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
312 System.Delegate.Combine(_serializableSavedHandlers, value);
313 else
314 _nonSerializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
315 System.Delegate.Combine(_nonSerializableSavedHandlers, value);
316 }
317 remove
318 {
319 if (value.Method.IsPublic &&
320 (value.Method.DeclaringType.IsSerializable ||
321 value.Method.IsStatic))
322 _serializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
323 System.Delegate.Remove(_serializableSavedHandlers, value);
324 else
325 _nonSerializableSavedHandlers = (EventHandler<Csla.Core.SavedEventArgs>)
326 System.Delegate.Remove(_nonSerializableSavedHandlers, value);
327 }
328 }
329
330 async Task<object> ISavable.SaveAsync()
331 {
332 return await SaveAsync();
333 }
334
335 async Task<object> ISavable.SaveAsync(bool forceUpdate)
336 {
337 return await SaveAsync(forceUpdate);
338 }
339
348 [EditorBrowsable(EditorBrowsableState.Advanced)]
349 protected virtual void OnSaved(T newObject, Exception e, object userState)
350 {
351 Csla.Core.SavedEventArgs args = new Csla.Core.SavedEventArgs(newObject, e, userState);
352 if (_nonSerializableSavedHandlers != null)
353 _nonSerializableSavedHandlers.Invoke(this, args);
354 if (_serializableSavedHandlers != null)
355 _serializableSavedHandlers.Invoke(this, args);
356 }
357
358 #endregion
359
360 #region Register Properties/Methods
361
376 {
377 return Core.FieldManager.PropertyInfoManager.RegisterProperty<P>(typeof(T), info);
378 }
379
387 protected static PropertyInfo<P> RegisterProperty<P>(string propertyName)
388 {
389 return RegisterProperty(Csla.Core.FieldManager.PropertyInfoFactory.Factory.Create<P>(typeof(T), propertyName));
390 }
391
399 protected static PropertyInfo<P> RegisterProperty<P>(Expression<Func<T, object>> propertyLambdaExpression)
400 {
401 PropertyInfo reflectedPropertyInfo = Reflect<T>.GetProperty(propertyLambdaExpression);
402 return RegisterProperty<P>(reflectedPropertyInfo.Name);
403 }
404
413 protected static PropertyInfo<P> RegisterProperty<P>(string propertyName, RelationshipTypes relationship)
414 {
415 return RegisterProperty(Csla.Core.FieldManager.PropertyInfoFactory.Factory.Create<P>(typeof(T), propertyName, string.Empty, relationship));
416 }
417
426 protected static PropertyInfo<P> RegisterProperty<P>(Expression<Func<T, object>> propertyLambdaExpression, RelationshipTypes relationship)
427 {
428 PropertyInfo reflectedPropertyInfo = Reflect<T>.GetProperty(propertyLambdaExpression);
429 return RegisterProperty<P>(reflectedPropertyInfo.Name, relationship);
430 }
431
440 protected static PropertyInfo<P> RegisterProperty<P>(string propertyName, string friendlyName)
441 {
442 return RegisterProperty(Csla.Core.FieldManager.PropertyInfoFactory.Factory.Create<P>(typeof(T), propertyName, friendlyName));
443 }
444
453 protected static PropertyInfo<P> RegisterProperty<P>(Expression<Func<T, object>> propertyLambdaExpression, string friendlyName)
454 {
455 PropertyInfo reflectedPropertyInfo = Reflect<T>.GetProperty(propertyLambdaExpression);
456 return RegisterProperty<P>(reflectedPropertyInfo.Name, friendlyName);
457 }
458
468 protected static PropertyInfo<P> RegisterProperty<P>(string propertyName, string friendlyName, P defaultValue)
469 {
470 return RegisterProperty(Csla.Core.FieldManager.PropertyInfoFactory.Factory.Create<P>(typeof(T), propertyName, friendlyName, defaultValue));
471 }
472
482 protected static PropertyInfo<P> RegisterProperty<P>(Expression<Func<T, object>> propertyLambdaExpression, string friendlyName, P defaultValue)
483 {
484 PropertyInfo reflectedPropertyInfo = Reflect<T>.GetProperty(propertyLambdaExpression);
485 return RegisterProperty(reflectedPropertyInfo.Name, friendlyName, defaultValue);
486 }
487
498 protected static PropertyInfo<P> RegisterProperty<P>(string propertyName, string friendlyName, P defaultValue, RelationshipTypes relationship)
499 {
500 return RegisterProperty(Csla.Core.FieldManager.PropertyInfoFactory.Factory.Create<P>(typeof(T), propertyName, friendlyName, defaultValue, relationship));
501 }
502
513 protected static PropertyInfo<P> RegisterProperty<P>(Expression<Func<T, object>> propertyLambdaExpression, string friendlyName, P defaultValue, RelationshipTypes relationship)
514 {
515 PropertyInfo reflectedPropertyInfo = Reflect<T>.GetProperty(propertyLambdaExpression);
516 return RegisterProperty(reflectedPropertyInfo.Name, friendlyName, defaultValue, relationship);
517 }
518
524 protected static MethodInfo RegisterMethod(string methodName)
525 {
526 return RegisterMethod(typeof(T), methodName);
527 }
528
534 protected static MethodInfo RegisterMethod(Expression<Action<T>> methodLambdaExpression)
535 {
536 System.Reflection.MethodInfo reflectedMethodInfo = Reflect<T>.GetMethod(methodLambdaExpression);
537 return RegisterMethod(reflectedMethodInfo.Name);
538 }
539
540 #endregion
541 }
542}
Provides consistent context information between the client and server DataPortal objects.
static bool AutoCloneOnUpdate
Gets a value indicating whether objects should be automatically cloned by the data portal Update() me...
object CreateInstanceDI(Type objectType, params object[] parameters)
Creates an object using 'Activator.CreateInstance' using service provider (if one is available) to po...
This is the base class from which most business objects will be derived.
Definition: BusinessBase.cs:38
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.
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.
override string ToString()
Returns a text representation of this object by returning the GetIdValue value in text form.
Definition: BusinessBase.cs:60
virtual object GetIdValue()
Override this method to return a unique identifying value for this object.
Definition: BusinessBase.cs:46
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.
Definition: BusinessBase.cs:79
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 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:33
Event arguments containing a reference to the new object that was returned as a result of the Save() ...
Client side data portal used for making asynchronous data portal calls in .NET.
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:467
Maintains metadata about a method.
Definition: MethodInfo.cs:19
MethodInfo(string name)
Creates an instance of the type.
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.