code首先&放大器;身份与Azure的存储表 [英] Code First & Identity with Azure Table Storage

查看:260
本文介绍了code首先&放大器;身份与Azure的存储表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作在一个小的web应用程序和我刚刚打了发展的地步,我要开始做数据库的决定。我原来的计划是与MSSQL先去EF code在Azure上,因为它只是简化了使用数据库的过程。然而,调查我的数据库托管在Azure上的能力的时候,我发现的Azure表的存储开辟了NoSQL的世界给我。

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 on Azure because it just simplifies the process of working with a database. However, when investigating my database hosting capabilities on Azure, I discovered Azure Table Storage which opened up the world of NoSQL to me.

尽管互联网起火有关的NoSQL的特点喋喋不休,我设法收集的最大原因之一就是NoSQL的存储整个对象为一体,在不破坏备份数据到各种表的数据库,这是良好的性能。虽然这听起来很吸引人,EF code首先,有效地通过自动的对象汇集对象和分离成一个SQL数据库没有一个开发商的每不必担心查询解决了这个问题。

While the Internet is ablaze with chatter about the features of NoSQL, one of the biggest reason I have managed to gather is that NoSQL stores entire objects as one in a database without breaking up the data into various tables which is good for performance. While this sounds appealing, EF Code First has effectively eliminated this problem by automatically pulling together objects and separating objects into a SQL database without a developer every having to worry about queries.

我的主要问题,但是,是我无法找到任何文件使用的东西像EF code首先和ASP.NET的身份与NoSQL数据库。由于我的应用程序目前使用的身份,我想,以避免切换到别的东西。

My main problem, however, is that I can't find any documentation to use things like EF Code First and ASP.NET Identity with NoSQL databases. Since my app currently uses Identity, I'd like to avoid having to switch to something else.

问:是否可以使用code首先和/或身份与Azure的表

编辑:我的应用作为一个极度简化了一点点,我的应用程序可以让我的用户通过混合和匹配preconfigured类型的数据创建自定义配置文件。例如,用户可以任意数量的引用对象添加到他们的个人资料,然后定义报价的值(即做你自己,其他人都已经被占用)。或者他们可以使用Movie对象来定义自己喜欢的电影集合(即标题:盗梦空间,年份:2010)。平均而言,一用户可以容易地有其第50页或更多这样的特性;有上,它们可具有属性的数目没有限制。

A little bit about my app As an extreme simplification, my app allows my users create custom profiles by mixing and matching preconfigured types of data. For example, a user can add any number of Quote objects to their profile and then define the value of the quote (i.e. "Be yourself; everyone else is already taken."). Or they can use a Movie object to define a collection of their favorite movies (i.e. "Title: Inception, Year: 2010"). On average, a user can easily have 50 or more such properties on their page; there is no limitation on the number of properties that they can have.

使用这个例子,我可以很容易地看我怎么会去使用code首先实现它(资料报价有对象的列表和Movie对象的列表)。我还没有确定如何,这将映射到一个NoSQL资料库,如天青表。所以,用我的应用程序的需求,我不知道,如果先从code切换到的NoSQL的特性和功能,我会失去一个合理的决定。

Using this example, I can easily see how I would go about implementing it using Code First (Profile has a list of Quote objects and a list of Movie objects). I'm not yet sure how this would map to a NoSQL database such as Azure Tables. So, with my app's needs, I'm not sure if switching from Code First to NoSQL a reasonable decision with the features and functionality I would lose.

推荐答案

因此​​,我们将有一个样品恰好针对这种情况,使用AzureTable存储作为一个没有SQL执行UserStore的。基本上你实现使用Azure存储API的一个IUserStore。下面是实现登录/密码方式的基本实现,但不是万能的:

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<string>();
        Claims = new List<Claim>();
        Logins = new List<AzureLogin>();
    }

    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<string> Roles { get; set; }
    public IList<AzureLogin> Logins { get; set; }
    public IList<Claim> Claims { get; set; }
}

public static class Constants {
    public const string IdentityPartitionKey = "ASP.NET Identity";
}

public class AzureStore : IUserStore<AzureUser>, IUserClaimStore<AzureUser>, IUserLoginStore<AzureUser>, IUserRoleStore<AzureUser>, IUserPasswordStore<AzureUser> {
    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<IList<Claim>> 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<AzureUser>.CreateAsync(AzureUser user) {
        TableOperation op = TableOperation.Insert(user);
        var result = Table.Execute(op);
        return Task.FromResult(0);
    }

    Task IUserStore<AzureUser>.UpdateAsync(AzureUser user) {
        TableOperation op = TableOperation.Replace(user);
        var result = Table.Execute(op);
        return Task.FromResult(0);
    }

    public Task<AzureUser> FindByIdAsync(string userId) {
        TableOperation op = TableOperation.Retrieve<AzureUser>(Constants.IdentityPartitionKey, userId);
        var result = Table.Execute(op);
        return Task.FromResult<AzureUser>(result.Result as AzureUser);
    }

    public Task<AzureUser> FindByNameAsync(string userName) {
        TableQuery<AzureUser> query = new TableQuery<AzureUser>().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<IList<UserLoginInfo>> GetLoginsAsync(AzureUser user) {
        TableQuery<AzureLogin> query = new TableQuery<AzureLogin>()
            .Where(TableQuery.GenerateFilterCondition("UserId", QueryComparisons.Equal, user.Id))
            .Select(new string[] { "LoginProvider", "ProviderKey" });
        var results = Table.ExecuteQuery(query);
        IList<UserLoginInfo> logins = new List<UserLoginInfo>();
        foreach (var al in results) {
            logins.Add(new UserLoginInfo(al.LoginProvider, al.ProviderKey));
        }
        return Task.FromResult(logins);
    }

    private AzureLogin Find(UserLoginInfo login) {
        TableQuery<AzureLogin> query = new TableQuery<AzureLogin>()
            .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<AzureUser> FindAsync(UserLoginInfo login) {
        var al = Find(login);
        if (al != null) {
            return FindByIdAsync(al.UserId);
        }
        return Task.FromResult<AzureUser>(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<IList<string>> GetRolesAsync(AzureUser user) {
        return Task.FromResult(user.Roles);
    }

    public Task<bool> IsInRoleAsync(AzureUser user, string role) {
        return Task.FromResult(false);
    }


    public Task DeleteAsync(AzureUser user) {
        throw new NotImplementedException();
    }

    public Task<string> GetPasswordHashAsync(AzureUser user) {
        return Task.FromResult(user.PasswordHash);
    }

    public Task<bool> HasPasswordAsync(AzureUser user) {
        return Task.FromResult(user.PasswordHash != null);
    }

    public Task SetPasswordHashAsync(AzureUser user, string passwordHash) {
        user.PasswordHash = passwordHash;
        return Task.FromResult(0);
    }
}

这篇关于code首先&放大器;身份与Azure的存储表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆