質問のタイトルは、実際のシナリオでは異なる意味を持つ可能性があります。
簡単な歴史:
Azure テーブルで CRUD 操作を行う既存のコードがあります。ただし、同じ Class タイプでしか InserOrMergeBatch できません。私が必要としているのは、基本クラスが同じである限り、異なるタイプのクラスを追加できるメソッドです。Partitionkey は別の方法で処理されるため、問題にはなりません。
ここに問題があります。
- 特定の基本クラスのキューを作成できるクラスを作成する
- 作成されたクラスは、必要な基本クラスを持っている限り、任意のタイプのオブジェクトを追加できる必要があります
たとえば、次の 2 つの基本クラスがあります: Human と Animal
public class Human
{
public int Height { get; set; }
public int Weight { get; set; }
}
public class Animal
{
public string Breed { get; set; }
public string Family { get; set; }
}
他のいくつかのクラスで使用されます:
public class Eye : Human
{
public string Color { get; set; }
}
public class Nose : Human
{
public string Type { get; set; }
}
public class Teeth : Human
{
public int Count { get; set; }
}
public class Dog : Animal
{
public string NoseColor { get; set; }
}
public class Cat : Animal
{
public string EyeColor { get; set; }
}
最初の問題は、いくつかの必須メソッドを持つクラスを作成することです。
public class AzureTableBatchCrud
{
public void CreateQueue( /* Specify the type of base class. */ )
{
}
public void AddQueue( /* Accept single object or list of objects of any type */ )
{
/* Must ensure that the added objects are inherited on same base class */
}
public bool ExecuteQueue()
{
/* Insert or merge objects on azure table */
return false;
}
}
より明確にするために、このクラスを使用してみましょう。
public class SampleUsage
{
public void SampleInsert()
{
// Example 1: Creating AzureTableBatchCrud with base class 'Human'
AzureTableBatchCrud sample1 = new AzureTableBatchCrud();
sample1.CreateQueue(Human);
// Right! because their base class is 'Human'
Eye eye1 = new Eye();
Nose nose1 = new Nose();
Teeth teeth1 = new Teeth();
sample1.AddQueue(eye1);
sample1.AddQueue(nose1);
sample1.AddQueue(teeth1);
// Wrong! because base class is not 'Human'
Dog dog1 = new Dog();
Cat cat1 = new Cat();
sample1.AddQueue(dog1); // must throw error
sample1.AddQueue(cat1); // must throw error
// Example 2: Creating AzureTableBatchCrud with base class 'Animal'
AzureTableBatchCrud sample2 = new AzureTableBatchCrud();
sample2.CreateQueue(Animal);
// Right! because base class is 'Animal'
Dog dog2 = new Dog();
Cat cat3 = new Cat();
sample2.AddQueue(dog2);
sample2.AddQueue(cat2);
// Wrong! because base class is not 'Animal'
Eye eye2 = new Eye();
Teeth teeth2 = new Teeth();
sample2.AddQueue(eye2); // must throw error
sample2.AddQueue(teeth2); // must throw error
}
}
例が問題の概念そのものを語っていることを願っています。
私は C# での基本的なコーディングを知っているだけで、この件に関しては、これは非常に高度なコーディングです。私は完全に考え違いです。どんな助けでも大歓迎です。
UPDATEクラス
のサンプルコードが必要だと思います。AzureTableBatchCrud
更新 2
読者が問題についてより多くのことを理解できるように、このコードを投稿しました。私はこのコードをテストしていませんが、同じ問題に遭遇した可能性のある将来の読者が参照できるように、問題が解決したらすぐに回答を投稿します。
namespace ProjectName.Domain.Entities
{
[DataContract]
public class NoSQLEntity: TableEntity
{
public NoSQLEntity()
{
}
public NoSQLEntity(string partitionKey, string rowKey)
{
PartitionKey = partitionKey;
RowKey = rowKey;
}
}
}
namespace ProjectName.Domain.Attribute
{
[System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple = false)]
public class AzureProjectionTable: System.Attribute
{
public string table;
}
}
namespace ProjectName.Data.DAOs
{
public class CrudBatch<T> where T : NoSQLEntity
{
private WomContext<T> _context;
CloudTable azuretable;
string table;
TableBatchOperation batchOperation;
List<T> itemlist;
public CrudBatch()
{
CloudStorageAccount storageAccount = ConfigWrapper.DataConnectionString();
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
var attrs = (Domain.Attribute.AzureProjectionTable[])
typeof(T).GetCustomAttributes(typeof(Domain.Attribute.AzureProjectionTable), true);
if (attrs.Length > 0)
table = attrs[0].table;
azuretable = tableClient.GetTableReference(table);
_context = new WomContext<T>(tableClient, table);
batchOperation = new TableBatchOperation();
itemlist = new List<T>();
}
public void AddQueue(object item)
{
var attrs = (Domain.Attribute.AzureProjectionTable[])
item.GetType().GetCustomAttributes(typeof(Domain.Attribute.AzureProjectionTable), true);
if (attrs.Length > 0)
{
if (table.Equals(attrs[0].table))
{
itemlist.Add((T)item);
}
}
}
public void AddQueue(List<object> item)
{
foreach (var i in item)
{
var attrs = (Domain.Attribute.AzureProjectionTable[])
i.GetType().GetCustomAttributes(typeof(Domain.Attribute.AzureProjectionTable), true);
if (attrs.Length > 0)
{
if (table.Equals(attrs[0].table))
{
itemlist.Add((T)i);
}
}
}
}
public bool ExecuteQueue(CrudAction action)
{
switch (action)
{
case CrudAction.InsertOrMergeBatch: return InsertOrMergeBatch();
case CrudAction.DeleteBatch: return DeleteBatch();
default: return false;
}
}
public void ClearQueue()
{
itemlist.Clear();
}
public T Get(string partitionKey, string rowKey)
{
TableOperation retrieve = TableOperation.Retrieve<T>(partitionKey, rowKey);
return (T)azuretable.Execute(retrieve).Result;
}
public IQueryable<T> Table()
{
return _context.Table;
}
private bool InsertOrMergeBatch()
{
foreach (var value in itemlist)
{
batchOperation.InsertOrMerge(value);
}
azuretable.ExecuteBatch(batchOperation).ToList();
return true;
}
private bool DeleteBatch()
{
TableBatchOperation batchOperation = new TableBatchOperation();
T deleteEntity;
foreach (var value in itemlist)
{
TableOperation retrieve = TableOperation.Retrieve<T>(value.PartitionKey, value.RowKey);
deleteEntity = (T)azuretable.Execute(retrieve).Result;
if (deleteEntity != null)
{
batchOperation.Delete(deleteEntity);
}
}
azuretable.ExecuteBatch(batchOperation);
return true;
}
}
public enum CrudAction
{
InsertOrMergeBatch,
DeleteBatch
}
}
namespace ProjectName.Data.Context
{
public class WomContext<T> : TableServiceContext where T: NoSQLEntity
{
private string table;
public WomContext(CloudTableClient client, string tablename)
: base(client)
{
table = tablename;
}
public TableServiceQuery<T> Table
{
get
{
return this.CreateQuery<T>(table).AsTableServiceQuery(this);
}
}
}
}
サンプルの基本クラスは次のようになります。
namespace ProjectName.Domain.Entities.Carts
{
[Attribute.AzureProjectionTable(table = BaseTableNames.Cart)]
public class Cart: NoSQLEntity
{
public Cart() : base()
{
}
public Cart(string partitionkey, string rowkey)
: base(partitionkey, rowkey)
{
}
// Some properties...
}
}