Code First & Identity with Azure Table Storage

前端 未结 4 1681
隐瞒了意图╮
隐瞒了意图╮ 2021-01-31 11:16

I\'m working on a small web app and I\'ve just hit the point in development where I need to start making database decisions. My original plan was to go EF Code First with MSSQL

4条回答
  •  说谎
    说谎 (楼主)
    2021-01-31 11:37

    So we will have a sample targeting exactly this scenario, using AzureTable storage as a no sql implementation of a UserStore. Basically you implement an IUserStore using the Azure Storage APIs. Here's a basic implementation that implements the login/password methods, but not everything:

    public class AzureRole : TableEntity, IRole {
        public string Id { get; set; }
        public string Name { get; set; }
    }
    
    public class AzureLogin : TableEntity {
        public AzureLogin() {
            PartitionKey = Constants.IdentityPartitionKey;
            RowKey = Guid.NewGuid().ToString();
        }
    
        public AzureLogin(string ownerId, UserLoginInfo info) : this() {
            UserId = ownerId;
            LoginProvider = info.LoginProvider;
            ProviderKey = info.ProviderKey;
        }
    
        public string UserId { get; set; }
        public string ProviderKey { get; set; }
        public string LoginProvider { get; set; }
    }
    
    public class AzureUser : TableEntity, IUser {
        public AzureUser() {
            PartitionKey = Constants.IdentityPartitionKey;
            RowKey = Guid.NewGuid().ToString();
            Id = RowKey;
            Roles = new List();
            Claims = new List();
            Logins = new List();
        }
    
        public AzureUser(string userName) : this() {
            UserName = userName;
        }
    
        public string Id { get; set; }
        public string UserName { get; set; }
        public string PasswordHash { get; set; }
        public string SecurityStamp { get; set; }
        public IList Roles { get; set; }
        public IList Logins { get; set; }
        public IList Claims { get; set; }
    }
    
    public static class Constants {
        public const string IdentityPartitionKey = "ASP.NET Identity";
    }
    
    public class AzureStore : IUserStore, IUserClaimStore, IUserLoginStore, IUserRoleStore, IUserPasswordStore {
        public AzureStore() {
            // Retrieve the storage account from the connection string.
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
    
            // CreateAsync the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
    
            // CreateAsync the table if it doesn't exist.
            CloudTable table = tableClient.GetTableReference("Identity");
            table.CreateIfNotExists();
            Table = table;
    
            BatchOperation = new TableBatchOperation();
        }
    
        public TableBatchOperation BatchOperation { get; set; }
        public CloudTable Table { get; set; }
    
        public void Dispose() {
        }
    
        public Task> GetClaimsAsync(AzureUser user) {
            return Task.FromResult(user.Claims);
        }
    
        public Task AddClaimAsync(AzureUser user, System.Security.Claims.Claim claim) {
            return Task.FromResult(0);
        }
    
        public Task RemoveClaimAsync(AzureUser user, System.Security.Claims.Claim claim) {
            return Task.FromResult(0);
        }
    
        Task IUserStore.CreateAsync(AzureUser user) {
            TableOperation op = TableOperation.Insert(user);
            var result = Table.Execute(op);
            return Task.FromResult(0);
        }
    
        Task IUserStore.UpdateAsync(AzureUser user) {
            TableOperation op = TableOperation.Replace(user);
            var result = Table.Execute(op);
            return Task.FromResult(0);
        }
    
        public Task FindByIdAsync(string userId) {
            TableOperation op = TableOperation.Retrieve(Constants.IdentityPartitionKey, userId);
            var result = Table.Execute(op);
            return Task.FromResult(result.Result as AzureUser);
        }
    
        public Task FindByNameAsync(string userName) {
            TableQuery query = new TableQuery().Where(TableQuery.GenerateFilterCondition("UserName", QueryComparisons.Equal, userName));
            return Task.FromResult(Table.ExecuteQuery(query).FirstOrDefault());
        }
    
        public Task AddLoginAsync(AzureUser user, UserLoginInfo login) {
            TableOperation op = TableOperation.Insert(new AzureLogin(user.Id, login));
            var result = Table.Execute(op);
            return Task.FromResult(0);
        }
    
        public Task RemoveLoginAsync(AzureUser user, UserLoginInfo login) {
            var al = Find(login);
            if (al != null) {
                TableOperation op = TableOperation.Delete(al);
                var result = Table.Execute(op);
            }
            return Task.FromResult(0);
        }
    
        public Task> GetLoginsAsync(AzureUser user) {
            TableQuery query = new TableQuery()
                .Where(TableQuery.GenerateFilterCondition("UserId", QueryComparisons.Equal, user.Id))
                .Select(new string[] { "LoginProvider", "ProviderKey" });
            var results = Table.ExecuteQuery(query);
            IList logins = new List();
            foreach (var al in results) {
                logins.Add(new UserLoginInfo(al.LoginProvider, al.ProviderKey));
            }
            return Task.FromResult(logins);
        }
    
        private AzureLogin Find(UserLoginInfo login) {
            TableQuery query = new TableQuery()
                .Where(TableQuery.CombineFilters(
                    TableQuery.GenerateFilterCondition("LoginProvider", QueryComparisons.Equal, login.LoginProvider),
                    TableOperators.And,
                    TableQuery.GenerateFilterCondition("ProviderKey", QueryComparisons.Equal, login.ProviderKey)))
                .Select(new string[] { "UserId" });
            return Table.ExecuteQuery(query).FirstOrDefault();
        }
    
        public Task FindAsync(UserLoginInfo login) {
            var al = Find(login);
            if (al != null) {
                return FindByIdAsync(al.UserId);
            }
            return Task.FromResult(null);
        }
    
        public Task AddToRoleAsync(AzureUser user, string role) {
            return Task.FromResult(0);
        }
    
        public Task RemoveFromRoleAsync(AzureUser user, string role) {
            return Task.FromResult(0);
        }
    
        public Task> GetRolesAsync(AzureUser user) {
            return Task.FromResult(user.Roles);
        }
    
        public Task IsInRoleAsync(AzureUser user, string role) {
            return Task.FromResult(false);
        }
    
    
        public Task DeleteAsync(AzureUser user) {
            throw new NotImplementedException();
        }
    
        public Task GetPasswordHashAsync(AzureUser user) {
            return Task.FromResult(user.PasswordHash);
        }
    
        public Task HasPasswordAsync(AzureUser user) {
            return Task.FromResult(user.PasswordHash != null);
        }
    
        public Task SetPasswordHashAsync(AzureUser user, string passwordHash) {
            user.PasswordHash = passwordHash;
            return Task.FromResult(0);
        }
    }
    

提交回复
热议问题