Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Added tests, fixed store bug(s)
  • Loading branch information
petero-dk committed Oct 20, 2022
commit 0b9f186f774bf55467fe1547117a6bd332aff0e9
121 changes: 121 additions & 0 deletions CoreHelpers.WindowsAzure.Storage.Table.Tests/ITS026RelatedTable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
using System;
using CoreHelpers.WindowsAzure.Storage.Table.Tests.Contracts;
using CoreHelpers.WindowsAzure.Storage.Table.Tests.Extensions;
using CoreHelpers.WindowsAzure.Storage.Table.Tests.Models;
using Xunit.DependencyInjection;

namespace CoreHelpers.WindowsAzure.Storage.Table.Tests
{
[Startup(typeof(Startup))]
[Collection("Sequential")]
public class ITS026RelatedTable
{
private readonly IStorageContext _rootContext;

public ITS026RelatedTable(IStorageContext context)
{
_rootContext = context;
}

[Fact]
public async Task ReadRelatedTable()
{
using (var storageContext = _rootContext.CreateChildContext())
{
// set the tablename context
storageContext.SetTableContext();
//
// create a new user
var user = new UserModel2() { FirstName = "Egon", LastName = "Mueller", Contact = "[email protected]" };
var demo = new DemoModel3() { P = "P2", R = "R2", UserContact = "[email protected]" };

// ensure we are using the attributes
storageContext.AddAttributeMapper();

// ensure the tables exists
await storageContext.CreateTableAsync<UserModel2>();
await storageContext.CreateTableAsync<DemoModel3>();

// inser the models
await storageContext.MergeOrInsertAsync<UserModel2>(user);
await storageContext.MergeOrInsertAsync<DemoModel3>(demo);

// query all
var result = await storageContext.QueryAsync<DemoModel3>();
Assert.Single(result);
Assert.Equal("Egon", result.First().User?.FirstName);
Assert.Equal("Mueller", result.First().User?.LastName);
Assert.Equal("[email protected]", result.First().User?.Contact);

// Clean up
user = result.First().User;
if (user != null)
await storageContext.DeleteAsync<UserModel2>(user);

var userResult = await storageContext.QueryAsync<UserModel2>();
Assert.NotNull(userResult);
Assert.Empty(userResult);


await storageContext.DeleteAsync<DemoModel3>(result);
result = await storageContext.QueryAsync<DemoModel3>();
Assert.NotNull(result);
Assert.Empty(result);

await storageContext.DropTableAsync<UserModel2>();
await storageContext.DropTableAsync<DemoModel3>();
}
}


[Fact]
public async Task WriteRelatedTable()
{
using (var storageContext = _rootContext.CreateChildContext())
{
// set the tablename context
storageContext.SetTableContext();
//
// create a new user
var user = new UserModel2() { FirstName = "Egon", LastName = "Mueller", Contact = "[email protected]" };
var demo = new DemoModel4() { P = "P2", R = "R2", UserContact = "[email protected]", User = user };

// ensure we are using the attributes
storageContext.AddAttributeMapper();

// ensure the tables exists
await storageContext.CreateTableAsync<UserModel2>();
await storageContext.CreateTableAsync<DemoModel4>();

// inser the model
await storageContext.MergeOrInsertAsync<DemoModel4>(demo);

// query all
var result = await storageContext.QueryAsync<DemoModel4>();
Assert.Single(result);
Assert.Equal("Egon", result.First().User?.FirstName);
Assert.Equal("Mueller", result.First().User?.LastName);
Assert.Equal("[email protected]", result.First().User?.Contact);

// Clean up
user = result.First().User;
if (user != null)
await storageContext.DeleteAsync<UserModel2>(user);

var userResult = await storageContext.QueryAsync<UserModel2>();
Assert.NotNull(userResult);
Assert.Empty(userResult);


await storageContext.DeleteAsync<DemoModel4>(result);
result = await storageContext.QueryAsync<DemoModel4>();
Assert.NotNull(result);
Assert.Empty(result);

await storageContext.DropTableAsync<UserModel2>();
await storageContext.DropTableAsync<DemoModel4>();
}
}
}
}

22 changes: 22 additions & 0 deletions CoreHelpers.WindowsAzure.Storage.Table.Tests/Models/DemoModel3.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using CoreHelpers.WindowsAzure.Storage.Table.Attributes;

namespace CoreHelpers.WindowsAzure.Storage.Table.Tests.Models
{
[Storable]
public class DemoModel3
{

[PartitionKey]
public string P { get; set; } = "P1";

[RowKey]
public string R { get; set; } = "R1";

public string UserContact { get; set; } = "[email protected]";

[RelatedTable("Partition01", RowKey = "UserContact")]
public UserModel2? User { get; set; }
}
}

22 changes: 22 additions & 0 deletions CoreHelpers.WindowsAzure.Storage.Table.Tests/Models/DemoModel4.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using CoreHelpers.WindowsAzure.Storage.Table.Attributes;

namespace CoreHelpers.WindowsAzure.Storage.Table.Tests.Models
{
[Storable]
public class DemoModel4
{

[PartitionKey]
public string P { get; set; } = "P1";

[RowKey]
public string R { get; set; } = "R1";

public string UserContact { get; set; } = "[email protected]";

[RelatedTable("Partition01", RowKey = "UserContact", AutoSave = true)]
public UserModel2? User { get; set; }
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@ public class RelatedTableAttribute : Attribute
/// </summary>
public bool AutoSave { get; set; }

//TODO:
//public bool AutoDelete { get; set; }

/// <summary>
///
/// </summary>
/// <param name="partitionKey">The partitionkey of the related table, if this is the name of a property on the model the property value will be used.</param>
public RelatedTableAttribute(string partitionKey)
{
PartitionKey = partitionKey;
AutoSave = false;
}

/// <summary>
Expand All @@ -37,7 +39,6 @@ public RelatedTableAttribute(string partitionKey, string rowKey)
{
PartitionKey = partitionKey;
RowKey = rowKey;
AutoSave = false;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
Expand Down Expand Up @@ -50,6 +51,8 @@ internal static class TableEntityDynamic
else if (relatedTableAttribute != null && relatedTableAttribute.AutoSave)
// TODO: Implicit save rowkey and partitionkey (will need to get from saved model)
SaveRelatedTable(context, property.GetValue(model, null), property).Wait();
else if (relatedTableAttribute != null)
continue;
else
builder.AddProperty(property.Name, property.GetValue(model, null));
}
Expand All @@ -60,6 +63,9 @@ internal static class TableEntityDynamic

private static async Task SaveRelatedTable(IStorageContext context, object o, PropertyInfo property)
{
if (o == null)
return;

Type endType;
if (property.PropertyType.IsDerivedFromGenericParent(typeof(Lazy<>)))
{
Expand All @@ -76,10 +82,17 @@ private static async Task SaveRelatedTable(IStorageContext context, object o, Pr
if (endType.IsDerivedFromGenericParent(typeof(IEnumerable<>)))
endType = endType.GetTypeInfo().GenericTypeArguments[0];
else
{
enumerableType = typeof(IEnumerable<>).MakeGenericType(endType);
Type listType = typeof(List<>).MakeGenericType(new[] { endType });
IList list = (IList)Activator.CreateInstance(listType);
list.Add(o);
o = list;
}

var method = typeof(StorageContext).GetMethod(nameof(StorageContext.StoreAsync),
new[] { typeof(nStoreOperation), enumerableType });
var method = typeof(StorageContext)
.GetMethods()
.Single(m => m.Name == nameof(StorageContext.StoreAsync) && m.IsGenericMethodDefinition);
var generic = method.MakeGenericMethod(endType);
var waitable = (Task)generic.Invoke(context, new object[] { nStoreOperation.insertOrReplaceOperation, o });
await waitable;
Expand Down