0

我有一个问题涉及基于登录用户在 SQL 数据库(实体框架)中返回数据行的后勤问题;我主要专注于桌面 C# 应用程序,在切换到 ASP.NET MVC 4 时,我在弄清楚这一点时遇到了一些困难(我四处搜索,似乎没有一个答案能提供确切的内容我在找):

我想使用 ASP.NET (MVC4) 内置的授权,并允许用户使用表单发布有关其网站的数据(站点类别、网址、年龄等),并让表单存储数据(使用Entity Framework)到与 UserProfile 表中的 Id 绑定的数据库(称为 PrimaryDomainsDb)。

当用户单击按钮以显示其域列表时,如何让应用程序拉取其域列表(相关数据行)而忽略其他用户行?

同样,我主要是在寻找物流和概念(例如使用外键)和伪代码,而不是实际上用勺子喂给我一堆代码。

如果有人有任何最佳实践想法(即以这种方式将 UserProfile 链接到 PrimaryDomainDb ,并使用 EF 以这种方式调用与其 Id 匹配的行以将行返回给视图),将不胜感激。

一些示例代码:

我目前首先像这样设置我的 PrimaryDomain 代码(这没有指定最小/最大长度等的装饰器):

public class PrimaryDomain
{
    public virtual int Id { get; set; }
    public virtual string SiteName { get; set; }
    public virtual string SiteURL { get; set; }
    public virtual SitePlatforms SitePlatform { get; set; }
    public virtual decimal? SiteDA { get; set; }
    public virtual decimal? SitePA { get; set; }
    public virtual string SiteAge { get; set; }
    public virtual DateTime? LastStatusUpdate { get; set; }
    public virtual string SiteIP { get; set; }
}

而且我有一个不同于 ASP.NET WebSecurity 提供的用户类,它看起来像这样:(另外,我知道“密码”不应该是字符串格式,这仅用于初始设置目的 -我认为应该完全删除密码并由 WebSecurity 处理)。

public class User
{
    public virtual int Id { get; set; }
    public virtual string Username { get; set; }
    public virtual string Password { get; set; }
    public virtual string Email { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual string MozAccessID { get; set; }
    public virtual string MozKey { get; set; }
    public virtual decimal AccuountBalance { get; set; }

    public virtual PrivateProxy PrivateProxies { get; set; }
    public virtual PrimaryDomain PrimaryDomains { get; set; }

}

在为 Views 提取数据时,我使用直接注入通过存储库运行所有内容:

public interface IUserDataSource
{
    IQueryable<User> Users { get; }
    IQueryable<PrimaryDomain> PrimaryDomains { get; }

    void Save();
}

这是我的 UserDb 类,每当代码调用 IUserDataSource(通过直接注入)时都会输入该类:

public class UserDb : DbContext, IUserDataSource
{
    public UserDb()
    : base("DefaultConnection")
    {
    }

    public DbSet<User> Users { get; set; }
    public DbSet<PrimaryDomain> PrimaryDomains { get; set; }



    IQueryable<User> IUserDataSource.Users
    {
        get { return Users; }
    }

    IQueryable<PrimaryDomain> IUserDataSource.PrimaryDomains
    {
        get { return PrimaryDomains; }
    }

    void IUserDataSource.Save()
    {
        SaveChanges();
    }
}

例如,这就是我如何将 PrimaryDomains 模型传递给视图:

public class NetworkController : Controller
{
    //
    // GET: /Network/
    private IUserDataSource _db;

    public NetworkController(IUserDataSource db)
    {
        _db = db;
    }

    public ActionResult ListDomains()
    {
        var allDomains = _db.PrimaryDomains;
        return View(allDomains);
    }
}

但不是从数据源中提取整个 PrimaryDomains 列表,我想添加一种方法来引用当前登录的用户 ID,以使应用程序仅显示该特定用户的域,而不是所有域,并且在添加新的域通过表单引用用户 ID 并将其添加到表中。

4

2 回答 2

0

这可能是您正在寻找的。如果我理解正确,您想使用 WebSecurity 登录或注册用户,但您想使用实体框架来存储一些特定于用户的数据。下面的代码将 WebSecurity 表与使用 EntityFramework 创建的数据库 CodeFirst 连接起来。

您在下面创建类(来自教程)。

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
    {
        private static SimpleMembershipInitializer _initializer;
        private static object _initializerLock = new object();
        private static bool _isInitialized;

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // Ensure ASP.NET Simple Membership is initialized only once per app start
            LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
        }

        private class SimpleMembershipInitializer
        {
            public SimpleMembershipInitializer()
            {
                try
                {
                    if(!WebSecurity.Initialized)
                        WebSecurity.InitializeDatabaseConnection("ConnectionString", "DbUsers", "UserId", "Email", autoCreateTables: true);
                }
                catch (Exception ex)
                {
                    throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
                }
            }
        }
    }

它为注册和记录用户创建必要的表。神奇之处在于第二、第三和第四个参数。它分别是您的数据库中的表、userId 列和 userName 列,您可以通过 EntityFramework 创建。WebSecurity 使用该表以及其他自行生成的表来管理您的用户并让他们注册、登录等。

然后在您的代码中首先您只需创建表

public class DbUser
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    [MaxLength(40)]
    public string Email { get; set; }
    [MinLength(3)]
    [MaxLength(30)]
    [Required]
    public string FirstName { get; set; }
    [MinLength(3)]
    [MaxLength(50)]
    [Required]
    public string LastName { get; set; }
}

然后您可以简单地从控制器查询数据。在下面的示例中,我使用 WebSecurity 成员存储的 UserId 从数据库中检索帐户信息。

public ActionResult AccountInfo()
        {
            if (FormsAuthentication.CookiesSupported == true && Request.Cookies[FormsAuthentication.FormsCookieName] != null)
            {
                var userId = WebSecurity.CurrentUserId;
                var userInfo = context.Users.FirstOrDefault(x => x.UserId == userId);
                userInfo.Password = "";
                return View(userInfo);
            }
            else
            {
                ModelState.AddModelError("", "Wystąpił bląd autoryzacji, zaloguj się jeszcze raz.");
                return RedirectToAction("Login", "Account");
            }
        }

编辑:

关于您编辑的问题,据我了解,除了您需要如上所述将 WebSecurity 与 EF 集成这一事实(我还忘记提及,在创建上述 InitializeSimpleMmebershipAttribute 类之后,您需要使用该属性装饰您的控制器)您也有实现通用的问题存储库。如果该行有问题:

var allDomains = _db.PrimaryDomains;

然后我建议阅读这篇关于实现通用存储库的文章:

http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net- mvc-应用程序

如果你想要事情真的很简单,你只需要添加到你的界面方法

GetDomainByUserId(int userId)

并像这样实现该接口:

public class UserDb : DbContext, IUserDataSource
{
    public UserDb()
    : base("DefaultConnection")
    {
    }

    public DbSet<User> Users { get; set; }
    public DbSet<PrimaryDomain> PrimaryDomains { get; set; }



    IQueryable<User> IUserDataSource.Users
    {
        get { return Users; }
    }

    IQueryable<PrimaryDomain> IUserDataSource.PrimaryDomains
    {
        get { return PrimaryDomains; }
    }

    IQueryable<PrimaryDomain> GetDomainByUserId(int userId)
    {
        return PrimaryDomains.Where(x => x.Id == userId).ToQueryable();
    }

    void IUserDataSource.Save()
    {
        SaveChanges();
    }
}

但这是非常糟糕的方法,我强烈建议阅读那篇文章。

于 2013-10-13T22:41:53.240 回答
0

我最初的问题可能对我想要达到的目标造成了一些混淆;摆出错误的方式去做我想做的事情是我的错。经过大量研究和学习,我发现我正在寻找的正是多租户数据架构方法。

于 2013-10-27T16:08:50.307 回答