Azure Mobile App使用现有数据库

我是第一次尝试使用Azure移动应用程序,我应该将其连接到现有的已填充的SQL Azure数据库。 据我所知,必须在表中添加VersionCreatedAtUpdatedAtDeleted列,最重要的是必须将id列设置为identity。

问题是在某些表上我已经有了一个标识列(例如ItemID ),如果不破坏连接到数据的现有第三方应用程序,我就无法重命名。

问题是:有没有办法避免使用身份标识字段,也许是某种方式映射原始身份?

[编辑]我已经看过网上的样本了,就像那样:

https://blogs.msdn.microsoft.com/azuremobile/2014/05/22/tables-with-integer-keys-and-the-net-backend/

但是移动服务移动应用程序之间似乎存在一些差异,如果有人指出我正确的方向,我真的很高兴,也许有一个可用的例子

通过一些调整,样本工作!

以此为教程的起点:

https://blogs.msdn.microsoft.com/wsdevsol/2014/07/17/walkthrough-attaching-an-azure-sql-database-to-your-net-backend/

这就是我所做的:

  1. *在我的表中添加了ITableData必填字段:

    [Version] ROWVERSION NOT NULL,
    [CreatedAt] DATETIMEOFFSET(7)DEFAULT(sysutcdatetime())NOT NULL,
    [UpdatedAt] DATETIMEOFFSET(7)NULL,
    [已删除] BIT DEFAULT((0))NOT NULL

  2. 使用EF Code First From数据库创建模型

  3. 仅使用数据字段创建DTO类,并inheritance自EntityData

  4. *像这样创建自定义MappingDomaninManager:

    public class MSSEntityDomainManager : MappedEntityDomainManager where TData : class, ITableData, new() where TModel : class { private Expression> dbKeyProperty; public MSSEntityDomainManager(MssContext context, HttpRequestMessage request, Expression> dbKeyProperty):base(context, request) { this.dbKeyProperty = dbKeyProperty; } public override Task DeleteAsync(string id) { return this.DeleteItemAsync(ConvertId(id)); } public override SingleResult Lookup(string id) { return this.LookupEntity(GeneratePredicate(id)); } public override Task UpdateAsync(string id, Delta patch) { return await this.UpdateEntityAsync(patch, ConvertId(id)); } private static Expression> GeneratePredicate(string id) { var m = Mapper.FindTypeMapFor(); var pmForId = m.GetExistingPropertyMapFor(new AutoMapper.Impl.PropertyAccessor(typeof(TData).GetProperty("Id"))); var keyString = pmForId.CustomExpression; var predicate = Expression.Lambda>( Expression.Equal(keyString.Body, Expression.Constant(id)), keyString.Parameters[0]); return predicate; } private object ConvertId(string id) { var m = Mapper.FindTypeMapFor(); var keyPropertyAccessor = GetPropertyAccessor(this.dbKeyProperty); var pmForId = m.GetExistingPropertyMapFor(new AutoMapper.Impl.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); } } } 

    与原始示例的不同之处在于从构造函数中完全删除了ApiServices引用,并将AutoMapper.Impl命名空间添加到PropertyAccessor,否则默认情况下它将使用System.Web.Http.OData

  5. *创建与实例中的SQL实用程序类完全相同的SQL实用程序类

     public static class MySqlFuncs { [DbFunction("SqlServer", "STR")] public static string StringConvert(long number) { return number.ToString(); } [DbFunction("SqlServer", "LTRIM")] public static string LTRIM(string s) { return s == null ? null : s.TrimStart(); } // Can only be used locally. public static long LongParse(string s) { long ret; long.TryParse(s, out ret); return ret; } } 

    这个我决定放入一个单独的“实用程序”文件

  6. *在Startup.MobileApp.cs文件中创建了映射,因为移动应用程序中不存在示例中提到的WebApiConfig.cs。 Automapper初始化代码按原样运行,我在HttpConfiguration config = new HttpConfiguration()之后就把它放了ConfigureMobileApp函数中。 以供参考:

     AutoMapper.Mapper.Initialize(cfg => { // Mapping from database type to client type cfg.CreateMap() .ForMember(dst => dst.Id, map => map.MapFrom(src => MySqlFuncs.LTRIM(MySqlFuncs.StringConvert(src.ID)))); // Mapping from client type to database type cfg.CreateMap() .ForMember(dst => dst.ID, map => map.MapFrom(src => MySqlFuncs.LongParse(src.Id))); }); 

标有“*”的是与原始msdnpost不同的点。 希望有人发现有帮助!