Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否通过记录对象的新实例更新TableServiceContext中的记录?_C#_Azure_Wcf Data Services_Azure Table Storage_Tableservicescontext - Fatal编程技术网

C# 是否通过记录对象的新实例更新TableServiceContext中的记录?

C# 是否通过记录对象的新实例更新TableServiceContext中的记录?,c#,azure,wcf-data-services,azure-table-storage,tableservicescontext,C#,Azure,Wcf Data Services,Azure Table Storage,Tableservicescontext,我已将azure表记录对象定义为 [DataServiceKey("PartitionKey", "RowKey")] public class TableRecord { public string PartitionKey { get; set; } public string RowKey { get; set; } public DateTime Timestamp { get; set; } public string Data { get; set;

我已将azure表记录对象定义为

[DataServiceKey("PartitionKey", "RowKey")]
public class TableRecord
{
    public string PartitionKey { get; set; }
    public string RowKey { get; set; }
    public DateTime Timestamp { get; set; }
    public string Data { get; set; }
}
记录用作存储库基础结构的一部分,存储库基础结构接受业务逻辑级别的数据对象,并在将代码保存到表存储之前将其序列化到数据属性中,以及在返回到客户端之前对其进行反序列化,因此,业务逻辑不知道有关记录以及PartitionKey和RowKey的任何信息

下面是存储库方法

public TEntity RegisterSave<TEntity>(TEntity entity, bool createNew)
{
    var storeRec = _strategy.GetStoreRecord(entity);
    if (createNew)
        _context.AddObject(storeRec.TableName, storeRec.Record);
    else
    {
        try
        {
            _context.AttachTo(storeRec.TableName, storeRec.Record, "*");                    
        }
        catch (InvalidOperationException)
        {
            // AttachTo can throw an exception if the entity is already being tracked.
            // Ignore
        }

        _context.UpdateObject(storeRec.Record);
    }
    return entity;
}

看看SDK v1.6中引入的Upsert功能

解决方案是,如果存在现有实体,则需要将其()分离,并将附件()分离到新实体。然后做你想做的更新

我写了一些代码来实现这一点。它还避免了抛出异常,尽管我不确定哪种方法更快

        /// <summary>
        /// Detach any existing rows with the same keys (if necessary), then attach to this object using the "*" ETag
        /// </summary>
        /// <param name="newEntity"></param>
        protected virtual void SafeAttach(TableServiceEntity newEntity)
        {
            TableServiceEntity entity = GetExistingRow(newEntity.PartitionKey, newEntity.RowKey);
            if(entity != null)
            {
                base.Detach(entity);
            }

            base.AttachTo("MY_TABLE_NAME_GOES_HERE", newEntity, "*");
        }

        private TableServiceEntity GetExistingRow(string partitionKey, string rowKey)
        {
            var query = (from e in base.Entities
                         where e.Entity is TableServiceEntity
                         && ((TableServiceEntity)e.Entity).RowKey == rowKey
                         && ((TableServiceEntity)e.Entity).PartitionKey == partitionKey
                         select (TableServiceEntity)e.Entity);

            RetrierFunctionResult<TableServiceEntity> r = StorageOperationRetrier.Execute(() =>
            {
                return query.FirstOrDefault();
            });

            return r.Result;
        }
//
///使用相同的键拆离任何现有行(如有必要),然后使用“*”ETag附加到此对象
/// 
/// 
受保护的虚拟void SafeAttach(表服务实体newEntity)
{
TableServiceEntity实体=GetExistingRow(newEntity.PartitionKey,newEntity.RowKey);
如果(实体!=null)
{
基础。分离(实体);
}
base.AttachTo(“我的表名在这里”,newEntity,“*”);
}
私有表服务实体GetExistingRow(string partitionKey,string rowKey)
{
var query=(来自base.Entities中的e)
其中e.Entity是表服务实体
&&((TableServiceEntity)e.Entity).RowKey==RowKey
&&((TableServiceEntity)e.Entity).PartitionKey==PartitionKey
选择(表服务实体)e.Entity);
RetrierFunctionResult=StorageOperationRetrier.Execute(()=>
{
返回query.FirstOrDefault();
});
返回r.Result;
}
要使用它,您需要调用
SafeAttach(storeRec)
来替换try/catch块

请注意,这种方法会破坏表存储的内置并发检查。你基本上得到了最后一次写赢的行为。这可能是可以接受的,也可能是不可以接受的,这取决于你的情况


此外,如果这是您计划继续工作的方式,您可能需要设置。不管怎样,您基本上是在模拟这种行为,禁用实体跟踪有一些性能优势

谢谢你的链接。不幸的是,这没有帮助-我仍然得到相同的错误-它们甚至在发出任何请求之前就被抛出。我只使用MergeOption.NotTracking,更简单的方法在我的方法中,表有一个负载字段数据,并且序列化了对象的最新版本。所以最后一次写赢的行为是我真正想要的。但看起来我错过了NoTracking选项背后的想法——它最适合这种情况。
        /// <summary>
        /// Detach any existing rows with the same keys (if necessary), then attach to this object using the "*" ETag
        /// </summary>
        /// <param name="newEntity"></param>
        protected virtual void SafeAttach(TableServiceEntity newEntity)
        {
            TableServiceEntity entity = GetExistingRow(newEntity.PartitionKey, newEntity.RowKey);
            if(entity != null)
            {
                base.Detach(entity);
            }

            base.AttachTo("MY_TABLE_NAME_GOES_HERE", newEntity, "*");
        }

        private TableServiceEntity GetExistingRow(string partitionKey, string rowKey)
        {
            var query = (from e in base.Entities
                         where e.Entity is TableServiceEntity
                         && ((TableServiceEntity)e.Entity).RowKey == rowKey
                         && ((TableServiceEntity)e.Entity).PartitionKey == partitionKey
                         select (TableServiceEntity)e.Entity);

            RetrierFunctionResult<TableServiceEntity> r = StorageOperationRetrier.Execute(() =>
            {
                return query.FirstOrDefault();
            });

            return r.Result;
        }