Skip to content

Commit

Permalink
DbDataAdapter: added Insert/Update/Delete overloads that accept only …
Browse files Browse the repository at this point in the history
…annotated object #17
  • Loading branch information
VitaliyMF committed Sep 18, 2016
1 parent fd4e440 commit e38d1a4
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 5 deletions.
7 changes: 4 additions & 3 deletions src/NReco.Data.Tests/DbDataAdapterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,19 +194,19 @@ public void InsertUpdateDelete_PocoModel() {
newCompany.Id = 5000; // should be ignored
newCompany.Name = "Test Super Corp";
newCompany.registered = false; // should be ignored
DbAdapter.Insert("companies", newCompany);
DbAdapter.Insert(newCompany);

Assert.True(newCompany.Id.HasValue);
Assert.NotEqual(5000, newCompany.Id.Value);

Assert.Equal("Test Super Corp", DbAdapter.Select(new Query("companies", (QField)"id"==(QConst)newCompany.Id.Value).Select("title") ).Single<string>() );

newCompany.Name = "Super Corp updated";
Assert.Equal(1, DbAdapter.Update(new Query("companies", (QField)"id"==(QConst)newCompany.Id.Value ), newCompany) );
Assert.Equal(1, DbAdapter.Update( newCompany) );

Assert.Equal(newCompany.Name, DbAdapter.Select(new Query("companies", (QField)"id"==(QConst)newCompany.Id.Value).Select("title") ).Single<string>() );

Assert.Equal(1, DbAdapter.Delete( new Query("companies", (QField)"id"==(QConst)newCompany.Id.Value )) );
Assert.Equal(1, DbAdapter.Delete( newCompany ) );
}


Expand All @@ -216,6 +216,7 @@ public class ContactModel {
public int? company_id { get; set; }
}

[Table("companies")]
public class CompanyModelAnnotated {

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
Expand Down
9 changes: 7 additions & 2 deletions src/NReco.Data/DataMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ PocoModelSchema InferSchema(Type t) {
keyCols.Add(colMapping);
cols.Add(colMapping);
}
return new PocoModelSchema(cols.ToArray(), keyCols.ToArray() );
var typeAttrs = t.GetCustomAttributes(true);
var tableAttr = typeAttrs.Where(a=>a is TableAttribute).Select(a=>(TableAttribute)a).FirstOrDefault();
return new PocoModelSchema( ( tableAttr?.Name ) ?? t.Name, cols.ToArray(), keyCols.ToArray() );
}

internal PocoModelSchema GetSchema(Type t) {
Expand Down Expand Up @@ -128,14 +130,17 @@ internal void MapTo(IDataRecord record, object o) {
}

internal class PocoModelSchema {

internal readonly string TableName;

internal readonly ColumnMapping[] Key;

internal readonly ColumnMapping[] Columns;

Dictionary<string,ColumnMapping> ColNameMap;

internal PocoModelSchema(ColumnMapping[] cols, ColumnMapping[] key) {
internal PocoModelSchema(string tableName, ColumnMapping[] cols, ColumnMapping[] key) {
TableName = tableName;
Columns = cols;
Key = key;
ColNameMap = new Dictionary<string, ColumnMapping>(Columns.Length);
Expand Down
49 changes: 49 additions & 0 deletions src/NReco.Data/DbDataAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,18 @@ public int Insert(string tableName, object pocoModel) {
});
return affected;
}

/// <summary>
/// Executes INSERT statement generated by annotated POCO model.
/// </summary>
/// <param name="pocoModel">POCO model (possibly annotated).</param>
/// <returns>Number of inserted data records.</returns>
public int Insert(object pocoModel) {
if (pocoModel==null)
throw new ArgumentNullException($"{nameof(pocoModel)}");
var schema = DataMapper.Instance.GetSchema(pocoModel.GetType());
return Insert(schema.TableName, pocoModel);
}

int UpdateInternal(Query q, IEnumerable<KeyValuePair<string,IQueryValue>> data) {
using (var updateCmd = CommandBuilder.GetUpdateCommand(q, data)) {
Expand Down Expand Up @@ -159,6 +171,32 @@ public int Update(Query q, object pocoModel) {
return UpdateInternal(q, DataHelper.GetChangeset( pocoModel, null) );
}

/// <summary>
/// Executes UPDATE statement generated by annotated POCO model.
/// </summary>
/// <param name="pocoModel">annotated POCO model (key should be defined).</param>
/// <returns>Number of updated data records.</returns>
public int Update(object pocoModel) {
if (pocoModel==null)
throw new ArgumentNullException($"{nameof(pocoModel)}");
return Update( GetQueryByKey(pocoModel), pocoModel);
}

Query GetQueryByKey(object pocoModel) {
var schema = DataMapper.Instance.GetSchema(pocoModel.GetType());
if (schema.Key.Length==0)
throw new ArgumentException("Specified object doesn't have properties annotated with KeyAttribute.");
var q = new Query(schema.TableName);
var andGroup = QGroupNode.And();
q.Condition = andGroup;
for (int i=0; i<schema.Key.Length; i++) {
var keyCol = schema.Key[i];
if (keyCol.GetVal!=null)
andGroup.Nodes.Add( (QField)keyCol.ColumnName == new QConst(keyCol.GetVal(pocoModel) ) );
}
return q;
}

void EnsurePrimaryKey(RecordSet recordSet) {
if (recordSet.PrimaryKey==null || recordSet.PrimaryKey.Length==0)
throw new NotSupportedException("Update operation can be performed only for RecordSet with PrimaryKey");
Expand Down Expand Up @@ -237,6 +275,17 @@ public int Delete(Query q) {
}
}

/// <summary>
/// Executes DELETE statement generated by annotated POCO model.
/// </summary>
/// <param name="pocoModel">annotated POCO model (key should be defined).</param>
/// <returns>Number of actually deleted records.</returns>
public int Delete(object pocoModel) {
if (pocoModel==null)
throw new ArgumentNullException($"{nameof(pocoModel)}");
return Delete( GetQueryByKey(pocoModel) );
}

/// <summary>
/// Asynchronously executes DELETE statement generated by specified <see cref="Query"/>.
/// </summary>
Expand Down
3 changes: 3 additions & 0 deletions src/NReco.Data/NetStandardCompatibility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ internal static bool _IsValueType(this Type t) {
internal static bool _IsEnum(this Type t) {
return t.GetTypeInfo().IsEnum;
}
internal static IEnumerable<Attribute> GetCustomAttributes(this Type t, bool inherit) {
return t.GetTypeInfo().GetCustomAttributes(inherit);
}
}
#else
internal static class Net40Compatibility {
Expand Down

0 comments on commit e38d1a4

Please sign in to comment.