从数据库表创建Model类的最佳方法是什么

时间:2019-06-11 19:57:06

标签: entity-framework model-view-controller model

我正在尝试使用一个表,假设数据库中的Account表包含20列左右的列,并且对于不同的视图,我要求使用不同的列,例如对于基本条目,我需要10个列来插入一个部门的数据,而需要5.5个其他列的数据。因此,将有3个需要数据或通过Model在该表之间进行通信的视图,那么最好的使用方法是: 1)创建3个模型,例如一个仅包含10个列,而其他5-5个? 2)仅使用包含所有列的单个模型。会不会携带不必要的数据?

我知道我们可以打破该表并使用关系来规范化数据,但是我只想了解有关登录模型和用户模型之类的最佳方法的更多信息。我们可以使用单一模型进行管理,因为我们都需要用户名和密码字段,但这是使用单一模型而不是2的正确方法吗?

1 个答案:

答案 0 :(得分:0)

Model和ViewModel代表不同的关注点。将它们分开。实体应反映数据状态,您可以在其中定义视图模型以支持不同的视图关注点。当您通过Entities从EF上下文中加载视图模型时,您使用public void saveOriginalSubtitles(SubtitlesHandler subtitles) { loadDatabase(); for (String text : subtitles.getOriginalSubtitles()) { System.out.println("text : " + text); try { PreparedStatement preparedStatement = connexion .prepareStatement("INSERT INTO translation.texte(texteATraduire, texteTraduit) VALUES(?, ?);"); preparedStatement.setString(1, text); preparedStatement.setString(2, " "); preparedStatement.executeUpdate(); connexion.close(); } catch (SQLException e) { System.out.println("erreur preparedStatement"); } } } private void loadDatabase() { try { Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { System.out.println("problème de driver mysql"); } try { Connection connexion = DriverManager.getConnection("jdbc:mysql://localhost:3306/translation", "hbstudent", "hbstudent"); } catch (SQLException e) { System.out.println("probleme de connexion à la base de données"); } finally { if ( connexion != null ) try { /* Fermeture de la connexion */ connexion.close(); } catch ( SQLException ignore ) { /* Si une erreur survient lors de la fermeture, il suffit de l'ignorer. */ } } } public void saveTranslatedSubtitles(Text texte) { loadDatabase(); try { PreparedStatement preparedStatement = connexion .prepareStatement("UPDATE texte SET texteTraduit = ?, WHERE id = ?"); preparedStatement.setString(1, texte.getTextTranslated()); preparedStatement.setInt(2, texte.getId()); preparedStatement.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } } 它将仅对视图模型所需的列构成有效的SQL查询。

例如,如果我有一个定义了20多个属性的Account实体,但是我想显示一个Accounts列表,仅列出其用户名,上次登录时间和角色列表:(其中“ “由AccountRoles表引用的Role的属性,该属性将帐户和角色之间的多对多链接)

.Select()

实体结构反映了您的数据结构,但是当服务器去查询那些实体以提供视图时,为要显示的数据结构定义ViewModel并利用EF组成查询来填充该视图模型。

您还可以通过其[Serializable] public class AccountSummaryViewModel { public string AccountName { get; set; } public DateTime LastLoginDateTime { get; set; } public ICollection<string> Roles { get; set; } = new List<string>(); } var accounts = MyContext.Accounts .Where(x => x.IsActive) .OrderBy(x => x.AccountName) .Select(x => new AccountSummaryViewModel { AccountName = x.AccountName, LastLoginDateTime = x.LastLoginDateTime, Roles = x.Roles.Select(x => x.Role.Name).ToList() }).ToList(); 方法将Automapper与EF的.ProjectTo<T>()实现集成在一起。

EF DbContext也只能注册一个与单个表关联的实体。若要使多种形式的实体指向一个Account表,您将需要多个DbContext定义。有界上下文对于大型系统很有用,但如果使用不当,则会导致纠缠在一起的上下文引用。

建议避免将实体传递到视图,因为这可能导致各种性能问题,异常以及安全漏洞,尤其是在控制器操作接受客户端返回的实体的情况下。通过将实体传递给客户端服务正在向客户端传递比其需要的更多信息,并且您在触发延迟加载调用或使用循环引用触发序列化方面遇到了潜在的问题。该系统还告诉黑客/竞争对手有关您的数据结构和数据的实际信息。 UI可能不会显示实体中的大多数信息,但是会将所有数据发送到客户端。这需要服务器/客户端上有更多内存,并且还需要通过网络提供更大的有效负载。