我正在使用ac#应用程序,您可以从combobox
中选择电影,并在datagrid
中显示电影信息及其中的演员,从MySql获取所有信息数据库。现在我已经搜索了我需要学习的大部分内容并将其实现到我的代码中。代码块看起来很大,并且想知道是否有任何方法可以将其干掉一些,例如我可以重用哪些变量等等。
//film select
var queryfilmsearch = "SELECT title, description, release_year, rental_rate, length, rating FROM film WHERE title LIKE + @value";
MySqlCommand cmdfilmsearch = new MySqlCommand(queryfilmsearch, PubVar.connection);
cmdfilmsearch.Parameters.AddWithValue("@value", comBoxFilm.Text);
MySqlDataAdapter adpfilmserach = new MySqlDataAdapter(cmdfilmsearch);
DataSet dsfilmsearch = new DataSet();
adpfilmserach.Fill(dsfilmsearch);
dataGridView1.ReadOnly = true;
dataGridView1.DataSource = dsfilmsearch.Tables[0];
//actor from film select
var queryfilmactor = "SELECT first_name, last_name FROM actor INNER JOIN film_actor ON actor.actor_id = film_actor.actor_id INNER JOIN film ON film.film_id = film_actor.film_id WHERE film.title LIKE + @value";
MySqlCommand cmdfilmactor = new MySqlCommand(queryfilmactor, PubVar.connection);
cmdfilmactor.Parameters.AddWithValue("@value", comBoxFilm.Text);
MySqlDataAdapter adpfilmactor = new MySqlDataAdapter(cmdfilmactor);
DataSet dsfilmactor = new DataSet();
adpfilmactor.Fill(dsfilmactor);
dataGridView2.ReadOnly = true;
dataGridView2.DataSource = dsfilmactor.Tables[0];
它基本上是相同的代码,只是不同的查询和变量名称
答案 0 :(得分:5)
这是很多样板文件,但并非必须如此。
首先,您使用的连接错误。他们实施IDisposable。你应该特别注意妥善处理它们。这意味着将它们存储为变量通常是个坏主意。尽快打开和关闭它们,不要共享它们。
其次,您使用的是原始ADO.NET。虽然了解ADO.NET如何工作是很好的(因为它是.NET中大多数关系数据库代码的构建块),但最好使用抽象。你最终写的文件更少了。更简洁,更易于阅读和重构代码。我们经常使用Object Relational Mappers来完成此任务。有两种风格:Micro和“full”。 .NET有几个微型ORM:Dapper,Npoco,PetaPoco等.Stack Overflow(网站)使用Dapper。然后是完整的ORM,例如Entity Framework和NHibernate。
您正在使用DataSet和DataTable。这些都是糟糕的抽象。它们不能很好地遵循面向对象编程原则,它们太灵活,而且效率低下。最好创建自定义类,然后使用某种形式的ORM从代码映射到自定义类。
您还可以直接在Web窗体中进行数据访问。这绝不是个好主意。数据库访问应该在单独的层中完成。这样可以更轻松地换出数据层或表示层,并且可以更轻松地在表示层的其他部分重用数据访问代码。
记住这一切,我们可能会得到类似下面的内容。我选择了Dapper。我假设Web表单,但我认为无论你的表示层是什么,你都会得到这个想法:
数据存储库
public class MySqlFilmRepository : IFilmRepository
{
readonly string _connectionString { get; set; }
public FilmRepsitory(string connectionString)
{
_connectionString = connectionString;
}
public List<Film> SearchFilmsByTitle(string title)
{
using (var connection = new MySqlConnection(_connectionString))
{
List<Film> films = connection.Query<Film>("SELECT title, description, release_year, rental_rate, length, rating FROM film WHERE title LIKE @Title", new { Title = title }).AsList();
return films;
}
}
public List<Actor> GetActorsForFilm(string filmTitle)
{
using (var connection = new MySqlConnection(_connectionString))
{
List<Actor> actors = connection.Query<Actor>("SELECT first_name, last_name FROM actor INNER JOIN film_actor ON actor.actor_id = film_actor.actor_id INNER JOIN film ON film.film_id = film_actor.film_id WHERE film.title LIKE @FilmTitle", new { FilmTitle = filmTitle }).AsList();
return actors;
}
}
}
public interface IFilmRepository
{
List<Film> SearchFilmsByTitle(string title);
List<Actor> GetActorsForFilm(string filmTitle);
}
模型类
public class Film
{
public string Title { get; set; }
public string Description { get; set; }
public int ReleaseYear { get; set; }
public decimal RentalRate { get; set; }
public int Length { get; set; }
public string Rating { get; set; }
}
public class Actor
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Web窗体代码:
IFilmRepository _filmRepository;
public void Page_Load (object sender, EventArgs e)
{
_filmRepository = new MySqlFilmRepository(ConfigurationManager.ConnectionStrings["MySqlConnectionString"].ConnectionString);
}
protected void SearchButton_Click(object sender, EventArgs e)
{
dataGridView1.DataSource = _filmRepository.SearchFilmsByTitle(SearchTextBox.Text);
dataGridView2.DataSource = _filmRepository.GetActorsForFilm(SearchTextBox.Text);
}
最终会有更多的代码,但现在您有一个集中的地方来进行数据调用,并且您正确处理连接,并且您可以使用更少的样板代码来查询数据库,并且它更灵活。这是更多的代码,但它也没有真正重复自己。