C#实体框架(代码优先),在模型上实现CRUD操作

时间:2018-06-12 03:51:56

标签: c# asp.net-mvc entity-framework

我只是想知道你是否可以在模型中存储一个函数(CRUD事务) 看起来像这样:

我的现有代码:

public class tbluser
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int id { get; set; }

    [Required(ErrorMessage = "Username is required")]
    public string username { get; set; }

    [Required(ErrorMessage = "Password is required")]
    public string password { get; set; }

    public static List<tbluser> list()
    {
        using (var db = new sample())
        {
            var user = db.tbluser.ToList();
            return user;
        }
    }
}

我想要的是什么:

public class tbluser:DbContext
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int id { get; set; }

    [Required(ErrorMessage = "Username is required")]
    public string username { get; set; }

    [Required(ErrorMessage = "Password is required")]
    public string password { get; set; }


    public static List<tbluser> list()
    {
        return this.toList();
    }
}

我只想问一下实现实体框架的方法是否正常。

3 个答案:

答案 0 :(得分:1)

像这样的代码会有很大的问题。

在第一个示例中,您将DbContext的实例紧密耦合到实体。调用tblUser.list()将返回User实体列表,但这些实体现在不在DbContext的范围内。 (由于using()块闭包这意味着任何延迟加载调用以检索相关实体都将失败,并且在重新附加到另一个DbContext之前,您无法对实体保留任何更改。这非常麻烦,非常快。

在第二个例子中,你将扩展一个DbContext,意思是每个&#34;实体&#34;有效地确定DbContext用途的范围,以填充自身的实例。你不能只是静止&#34;包装该方法,因为它不具有从DbContext继承的非静态DbSets的可见性。

这在性能方面会很糟糕,从代码的角度来看,这看起来很奇怪:

即。

using (var user = new tbluser)
{
   var users = user.list(); // not static.
   // .. Do stuff..
}

要使其静态会有问题,因为DbContext需要在tbluser内部进行静态作用

public class tbluser
{
   private static MyContext _context = new MyContext();

   // ...

   public static List<tbluser> list()
   {
      return _context.tblusers.ToList();
   }
}

这可能仍然存在问题,例如静态实例在远程运行之前是如何处理的,但我当然不能推荐这样的方法。

相反,请按预期使用DbContext。查看像Unity或Autofac这样的IoC容器来管理DbContext的生命周期范围,并将实例作为依赖项注入需要它的类中,或者至少将其包装在using() {}块中并将其视为存储库用它的DbSets。

有很多使用DbContext的示例,使用Repositories和Unit of Work模式以及依赖注入。在尝试开发独特的东西之前掌握这些。未来的开发人员会查看您的代码,谢谢您。 :)

答案 1 :(得分:1)

有一个着名的原则叫做#34; Separation of Concerns&#34;如果你这样做会很生气我的建议是保持代码简单,有意义和松散耦合。

答案 2 :(得分:1)

以下是一个快速示例,说明如何设置一个简单的Code First实现来开始。

首先,定义您的用户模型。整数类型的Key属性会自动为您配置identity属性。然后,如果您打算通过用户名进行频繁查找(获取用户详细信息或验证密码),您可能需要用户名的索引。

public class User
{
    [Key] // Becomes identity by default
    public int Id { get; set; }
    [Index("IX_User_Username", IsUnique = true)]
    public string Username { get; set; }
    public string Password { get; set; }
}

然后,您可以定义

public class AppDataContext : DbContext
{
    public AppDataContext() : base("name=DBConnection") { }
    public DbSet<User> Users { get; set; }
}

您只需要确保配置文件中有一个连接字符串,以匹配传递的名称。

<connectionStrings>
    <add name="DBConnection"  providerName="System.Data.SqlClient"
        connectionString="Data Source=instancePath;Initial Catalog=dbName;Integrated Security=true;MultipleActiveResultSets=True" />
</connectionStrings>

这将允许您创建如下的回购:

public class UserRepo : IDisposable
{
    public Lazy<AppDataContext> _db = new Lazy<AppDataContext>(() => new AppDataContext());

    public IQueryable<User> Get() => _db.Value.Users.AsQueryable();
    public IList<User> GetAll() => _db.Value.Users.ToList();

    public void Dispose()
    {
        if (_db.IsValueCreated)
            _db.Value.Dispose();
    }
}

那么你可以直接使用repo或上下文。

// Use the repo
using (var userRepo = new UserRepo())
{
    var allUsers = userRepo.GetAll();
    var user = userRepo.Get().FirstOrDefault(m => m.Username == "myUsername");
}
// Or just use the data context
using (var db = new AppDataContext())
{
    var allUsers = db.Users.ToList(); // Get all users
    var user = db.Users.FirstOrDefault(m => m.Username == "myUsername");
}

有关详细信息,请参阅以下链接: