-
Notifications
You must be signed in to change notification settings - Fork 2
BizArk.Core.Data.BaObject
Back to BizArk.Core API Reference
BaObject provides the features needed when working with data intensive code. If you have an ORM that is causing more work then it is saving, BaObject could be a viable alternative, especially when combined with the BizArk.Data.SqlServer project.
BaObject can be used without having to populate it from the database first. Just instantiate the object, set the fields you want to save, then save just the changed fields to the database.
Another benefit of BaObject is that you don't need to change your code when the database schema changes. When BaObject is loaded from a database object (such as IDataReader or DataRow), it will simply take on the structure of whatever it is given. Send the object to the client as dynamic and don't worry about strongly typing data that is simply being pushed into and retrieved from a database.
BaObject also supports data validation. When created from a database object (such as IDataReader or DataRow), it will automatically create the validation rules it has available (such as DataType, Required, MaxLength, etc). You can add additional validation rules as needed to the BaField objects. See BizArk.Core.Data.BaObject Validation for more information about validation.
-
IDynamicMetaObjectProvider- Allows this object to be used as a dynamic object. -
IDictionary<string, object>- Allows this object to be used as a property bag (a common type of object used throughout BizArk) without having to convert it. -
INotifyPropertyChanged- Provides an event to notify when a field changes value.
-
public BaFieldList Fields { get; }- Gets the fields in this object. -
public bool HasChanged { get; }- Gets a value that determines if the object has changed. -
public BaObjectOptions Options { get; }- Gets the options object used to create the BaObject. See BaObjectOptions -
public object this[string fldName]- Gets or sets the value for the given field.
-
public BaField Add<T>(string fldName, T dflt)- Adds the field to the object. -
public BaField Add(string fldName, Type fldType, object dflt)- Adds the field to the object. -
public void Fill(object data)- Fills this instance with data. Only sets fields that are in the schema (others are ignored). -
public virtual IDictionary<string, object> GetChanges(params string[] ignore)- Returns a dictionary of changed values. -
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)- Raises the PropertyChanged event. -
protected internal void OnPropertyChanged(string fldName)- Raises the PropertyChanged event. -
public bool TryGet(string fldName, out object result)- Tries to get the value. Returns true if the value is in the object or if strict is false. -
public bool TrySet(string fldName, object value)- Tries to set the value. If strict is off and the field is not found, it will be added. -
public void UpdateDefaults()- Updates the default value to be the same as value so that the fields show up as not changed. -
public ValidationResult[] Validate(bool changedOnly = true)- Uses DataAnnotations to validate the properties of the object.
-
public event PropertyChangedEventHandler PropertyChanged- Event raised when a field value changes.
This example uses a simple anonymous type to initialize the schema. A real-world application is more likely to use an IDataReader or DataRow to initialize the schema.
var baObj = new Core.Data.BaObject(true, new { Nbr = 123, Str = (string)null });
baObj.Fields["Nbr"].Validators.Range(0, 1000);
dynamic obj = baObj;
// Prints "Nbr: 123, Str: []"
Console.WriteLine($"Nbr: {obj.Nbr:N0}, Str: [{obj.Str}]");
obj.Nbr = 1234;
obj.Str = "Hello World";
// Prints "Nbr: 1,234, Str: [Hello World]"
Console.WriteLine($"Nbr: {obj.Nbr:N0}, Str: [{obj.Str}]");
// Prints "The field Nbr must be between 0 and 1000."
var errs = baObj.Validate();
foreach (var err in errs)
Console.WriteLine(err.ErrorMessage);
// Throws an InvalidOperationException
obj.Nbr = "Not a number!";If you really want a strongly typed object, you can derive it from BaObject and use the BaObject to store the data. This gives you the best of both worlds (though now you have to support a strongly typed object).
public class MyObject : BaObject
{
public MyObject() : base(true)
{
// Initialize the schema from this object, but don't get
// default values (that would cause the class to call the
// properties which would fail).
InitSchemaFromObject(this, false);
Fields["Name"].Validators
.Required()
.StringLength(10)
.Custom((val) =>
{
var name = val as string;
if (name.IsEmpty()) return true;
return !name[0].IsVowel(); // The name cannot start with a vowel.
});
Fields["Greeting"].Validators
.Required()
.StringLength(3, 10);
}
public string Name
{
get { return (string)this[nameof(Name)]; }
set { this[nameof(Name)] = value; }
}
public string Greeting
{
get { return (string)this[nameof(Greeting)]; }
set { this[nameof(Greeting)] = value; }
}
}Although there are plenty of reasons to use this class as-is, it works really well with the BizArk.Data.SqlServer project. The SqlServer project includes a BaTableObject class that inherits from BaObject and is intended to wrap a database table schema. A BaTableObject can be saved to the database by calling BaRepository.Save(BaTableObject). Only values that have been set after instantiating the object will be saved.
For web applications (including APIs), a best practice is to use simple BaObject objects when getting data out of the database. These objects can support arbitrary data sets without worrying about schemas. When data is being saved back to the database, use BaTableObject to set just the values that changed and validate them before saving the data.