0

你知道我如何在没有实体的关键属性的情况下使用 OData 语法更新 WCF 数据服务中的实体。

例如,一个实体:

public class Product
{
    [Key]
    public int Id { get; set; }

    public string Reference { get; set; }
}

我想提出这个要求:

PUT myservice.svc/Product('REFXX') 

与 'REFXXX' 对应的做参考属性(这是唯一的)。

任何的想法?

4

2 回答 2

0

目前没有办法做到这一点 - 问题是如果您将以下请求传递给服务器 (PUT myservice.svc/Product('REFXX')),服务器如何知道 REFXX 是唯一属性的值和不是关键属性。

如果您真的想根据唯一属性更新客户端,请确保服务器将该唯一属性公开为键。

谢谢普拉蒂克

于 2013-01-18T00:58:03.330 回答
0

我写了一个IDispatchMessageInspector,解析url并用正确的语法和真正的键替换请求参数中的匹配元素。我知道密钥不是具有特定用户代理或语法 Service.svc/Entity(SecondaryKey=value) 的真正“密钥”,通常用于多个 pk。

所以在方法 AfterReceiveRequest 中的过程是:

  • 解析 url Service.svc/Entity(SecondaryKey=value)
  • 获取实体的键值(通过构建动态 linq 表达式)
  • 使用 Service.svc/Entity(PKValue) 更改请求的匹配元素

           public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
    {
    
        if (request.Properties.ContainsKey("UriTemplateMatchResults") && HttpContext.Current != null)
        {
            //get match for current request
            UriTemplateMatch match = (UriTemplateMatch)request.Properties["UriTemplateMatchResults"];
    
            Utils.ODataBasicUriParser uriParser = new Utils.ODataBasicUriParser(match.RequestUri.PathAndQuery);
    
            //verify if this is a SecondaryKey request
            if (uriParser.IsEntityQuery && uriParser.IsSecondaryKeyQuery)
            {               
                //TODO this syntax is also used for entities with multiple pk's, test it
    
                //get a new data context
                //TODO see if this can be improved, avoid two datacontext for one request 
                DataContext ctx = new DataContext();
    
                Type outType;
                //get entity type name from the service name 
                string entityName = DataContext.GetEntityNameByServiceName(uriParser.EntityServiceName);
    
                //get the pk for the entity
                string id = ctx.GetEntityId(entityName, uriParser.EntityKey, uriParser.EntityId, out outType);
    
                //verify if the pk has been found or cancel this to continue with standart request process
                if (string.IsNullOrEmpty(id))
                {
                    Trace.TraceWarning(string.Format("Key property not found for the the entity:{0}, with secondaryKeyName:{1} and secondaryKeyValue:{2}",
                        entityName, uriParser.EntityKey, uriParser.EntityId));
    
                    return System.Net.HttpStatusCode.NotFound;
                }
    
                //in odata syntax quotes are required for string values, nothing for numbers
                string quote = outType.FullName == typeof(Int32).FullName || outType.FullName == typeof(Int64).FullName ? string.Empty : "'";
    
                //build the new standart resource uri with the primary key
                var newUri = new Uri(string.Format("{0}/{1}({2}{3}{2})", match.BaseUri.ToString(), uriParser.EntityServiceName, quote, id));
    
                //create a new match to replace in the current request, with the new Uri
                UriTemplateMatch newMatch = NewMatch(match, newUri); 
    
                //set request values
                request.Properties["UriTemplateMatchResults"] = newMatch;
                request.Headers.To = newUri;
                request.Properties.Via = newUri;
            }
        }
    
        return null;
    }
    
    
    UriTemplateMatch NewMatch(UriTemplateMatch match, Uri newUri)
    {
        UriTemplateMatch newMatch = new UriTemplateMatch();
        newMatch.RequestUri = newUri;
        newMatch.Data = match.Data;
        newMatch.BaseUri = match.BaseUri;
    
        return newMatch;
    }
    

适用于我当前的需求

于 2013-01-18T16:32:45.007 回答