2016-04-27 2 views
0

Мы разрабатываем лазурные мобильные службы, используя подход первой базы данных с существующей базой данных. Мы добавили столбец Id, CreatedAt, UpdateAt, Version в таблицу require.Устранение неполадок внешнего ключа и [Key] в методе POST/PATCH в лазурных мобильных услугах

В проекте SimpleMappedEntityDomainManager.cs используется для класса отображения домена. См. Прилагаемый файл класса здесь. Инициализировать метод каждого контроллера, создав экземпляр домена с использованием этого класса, как показано ниже.

public class SimpleMappedEntityDomainManager<TData, TModel> 
    : MappedEntityDomainManager<TData, TModel> 
    where TData : class, ITableData, new() 
    where TModel : class 
{ 
    private Expression<Func<TModel, object>> dbKeyProperty; 

    public SimpleMappedEntityDomainManager(DbContext context, 
     HttpRequestMessage request, 
     Expression<Func<TModel, object>> dbKeyProperty) 
     : base(context, request, true) 
    { 
     this.dbKeyProperty = dbKeyProperty; 
     //this.Context = context; 
    } 
    public override SingleResult<TData> Lookup(string id) 
    { 
     return this.LookupEntity(GeneratePredicate(id)); 
    } 
    public override async Task<TData> UpdateAsync(string id, Delta<TData> patch) 
    { 
     return await this.UpdateEntityAsync(patch, id); 
    } 
    public override Task<bool> DeleteAsync(string id) 
    { 
     return this.DeleteItemAsync(id); 
    } 

    private static Expression<Func<TModel, bool>> GeneratePredicate(string id) 
    { 
     var m = Mapper.FindTypeMapFor<TModel, TData>(); 
     var pmForId = m.GetExistingPropertyMapFor(new PropertyAccessor(typeof(TData).GetProperty("Id"))); 
     var keyString = pmForId.CustomExpression; 
     var predicate = Expression.Lambda<Func<TModel, bool>>(
      Expression.Equal(keyString.Body, Expression.Constant(id)), 
      keyString.Parameters[0]); 
     return predicate; 
    } 

    private object ConvertId(string id) 
    { 
     var m = Mapper.FindTypeMapFor<TData, TModel>(); 
     var keyPropertyAccessor = GetPropertyAccessor(this.dbKeyProperty); 
     var pmForId = m.GetExistingPropertyMapFor(new PropertyAccessor(keyPropertyAccessor)); 
     TData tmp = new TData() { Id = id }; 
     var convertedId = pmForId.CustomExpression.Compile().DynamicInvoke(tmp); 
     return convertedId; 
    } 

    private PropertyInfo GetPropertyAccessor(Expression exp) 
    { 
     if (exp.NodeType == ExpressionType.Lambda) 
     { 
      var lambda = exp as LambdaExpression; 
      return GetPropertyAccessor(lambda.Body); 
     } 
     else if (exp.NodeType == ExpressionType.Convert) 
     { 
      var convert = exp as UnaryExpression; 
      return GetPropertyAccessor(convert.Operand); 
     } 
     else if (exp.NodeType == ExpressionType.MemberAccess) 
     { 
      var propExp = exp as System.Linq.Expressions.MemberExpression; 
      return propExp.Member as PropertyInfo; 
     } 
     else 
     { 
      throw new InvalidOperationException("Unexpected expression node type: " + exp.NodeType); 
     } 
    } 
} 

существующую таблицу, как показано ниже:

Стол: tbl_Property_equip

  1. property_equip_id - идентичность столбца первичного ключа
  2. PROPERTY_ID
  3. equipment_id
  4. property_equip_serial_number property_equip_unit_number

Стол: tbl_property_loc

  1. property_loc_id - идентичность столбца первичного ключа
  2. PROPERTY_ID
  3. property_loc_name

Стол: tbl_property_equip_area_served

  1. property_equip_area_served_id - идентичность столбца первичного ключа
  2. property_equip_id - tbl_Property_equip таблица ссылка
  3. property_loc_id - tbl_property_loc таблица ссылка

Модель Класс genereated, как показано ниже:

public partial class tbl_property_equip { 
    //[Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int property_equip_id { get; set; } 

    public int property_id { get; set; } 

    public int equipment_id { get; set; } 

    [StringLength(150)] 
    public string property_equip_serial_number { get; set; } 

    [StringLength(150)] 
    public string property_equip_unit_number { get; set; } 

    public virtual ICollection<tbl_property_equip_area_served> tbl_property_equip_area_served { get; set; } 
} 

public partial class tbl_property_loc 
{ 
    //[Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int property_loc_id { get; set; } 

    public int property_id { get; set; } 

    [StringLength(255)] 
    public string property_loc_name { get; set; } 

    public virtual ICollection<tbl_property_equip_area_served> tbl_property_equip_area_served { get; set; } 
} 

public partial class tbl_property_equip_area_served 
{ 
    //[Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int property_equip_area_served_id { get; set; } 

    public int property_equip_id { get; set; } 

    public int property_loc_id { get; set; } 

    public virtual tbl_property_equip tbl_property_equip { get; set; } 

    public virtual tbl_property_loc tbl_property_loc { get; set; } 
} 

метод POST/PATCH работает отлично для оборудования и имущества Местонахождение недвижимости, в связи с удаленной [KEY] и DatabaseGeneratedOption.Identity. Здесь не рассматривался ID как первичный ключ.

Но свойство Area Served не работает из-за удаления [KEY] из имущества и класса местоположения. так что это идентификатор ID как первичный ключ для каждого. Отношения с родительским столом не работают должным образом. поэтому ниже ошибка, показанная в почтальоне.

{ 
    "message": "An error has occurred.", 
    "exceptionMessage": "One or more validation errors were detected during model generation:\r\n\r\ntbl_property_loc_tbl_property_equip_area_served_Source_tbl_property_loc_tbl_property_equip_area_served_Target: : The types of all properties in the Dependent Role of a referential constraint must be the same as the corresponding property types in the Principal Role. The type of property 'property_loc_id' on entity 'tbl_property_equip_area_served' does not match the type of property 'Id' on entity 'tbl_property_loc' in the referential constraint 'tbl_property_loc_tbl_property_equip_area_served'.\r\ntbl_property_equip_tbl_property_equip_area_served_Source_tbl_property_equip_tbl_property_equip_area_served_Target: : The types of all properties in the Dependent Role of a referential constraint must be the same as the corresponding property types in the Principal Role. The type of property 'property_equip_id' on entity 'tbl_property_equip_area_served' does not match the type of property 'Id' on entity 'tbl_property_equip' in the referential constraint 'tbl_property_equip_tbl_property_equip_area_served'.\r\n", 
"exceptionType": "System.Data.Entity.ModelConfiguration.ModelValidationException", 
    "stackTrace": " at System.Data.Entity.Core.Metadata.Edm.EdmModel.Validate()\r\n at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)\r\n at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)\r\n at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)\r\n at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)\r\n at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()\r\n at System.Data.Entity.Internal.InternalContext.Initialize()\r\n at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)\r\n at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()\r\n at System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()\r\n at System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName)\r\n at System.Data.Entity.Internal.Linq.InternalSet`1.Add(Object entity)\r\n at System.Data.Entity.DbSet`1.Add(TEntity entity)\r\n at Microsoft.Azure.Mobile.Server.MappedEntityDomainManager`2.<InsertAsync>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n at Microsoft.Azure.Mobile.Server.TableController`1.<InsertAsync>d__3.MoveNext()" 
} 

Я попытался создать класс Domain Mapper для таблицы обслуживаемых областей свойств, как указано в примере ниже. Но успех не мог.мы будем использовать такой же подход для существующей базы данных в качестве приведенного здесь примера.

https://azure.microsoft.com/en-us/documentation/articles/mobile-services-dotnet-backend-use-existing-sql-database/

Пожалуйста направьте нам.

ответ