私は最近、ADO.NET Entity Frameworkの学習と使用を開始し、いくつかの問題にぶつかりました。ネットワークに接続されている別のコンピュータのデータベースに接続できないため、ルータへのWi-Fi接続が切断されることがあります。接続が失敗すると、アプリケーション全体が約20秒間フリーズし、その後例外がスローされます。私は例外をキャッチして代わりにカスタムエラーメッセージを表示したいが、私はすべてのクエリの周りにtry-catchを使いたくない。.NET Entity Frameworkの接続に失敗しました
これは私がやろうとしたものです。私は、必要なたびにコンテキストを作成するための静的メソッドを作成し、try-catchステートメント内にラップして接続エラーをキャッチし、接続がないか、ユーザーがMessaeBoxにNoと答えてから終了します。応用。
public static MySqlEntities Database
{
get
{
try
{
// create a new context
MySqlEntities db = new MySqlEntities();
// return it upon success
return db;
}
catch (Exception ex)
{
// show error message upon failute
MessageBoxResult result = MessageBox.Show("Failed to establish a connection with the database. Please verify that the database server is online, would you like to try again?", "Database Connection Failure", MessageBoxButton.YesNo);
// close the application if they don't wanna try again
if (result == MessageBoxResult.No)
{
Fx.Window.Close();
return null;
}
// otherwise try again
return Fx.Database;
}
}
}
ここでは、データベースとの間でデータの選択、更新、追加を行うために書いたリポジトリクラスについて説明します。
public class EmployeeRepository
{
#region SelectQuery
/// <summary>
/// Compiled query for selecting a range of Employees.
/// </summary>
protected static readonly Func<MySqlEntities, int, int, IQueryable<Employee>> SelectQuery =
CompiledQuery.Compile<MySqlEntities, int, int, IQueryable<Employee>>(
(db, start, limit) =>
(from t in db.Employees orderby t.ID select t).Skip(start).Take(limit)
);
#endregion
#region SelectyByIDQuery
/// <summary>
/// Compiled query for selecting a single Employee by ID.
/// </summary>
protected static readonly Func<MySqlEntities, int, Employee> SelectByIDQuery =
CompiledQuery.Compile<MySqlEntities, int, Employee>(
(db, id) =>
(from t in db.Employees where t.ID == id select t).FirstOrDefault()
);
#endregion
#region SelectByUsernameQuery
/// <summary>
/// Compiled query for selecting a single Employee by Username.
/// </summary>
protected static readonly Func<MySqlEntities, string, Employee> SelectByUsernameQuery =
CompiledQuery.Compile<MySqlEntities, string, Employee>(
(db, username) =>
(from t in db.Employees where t.Username == username select t).FirstOrDefault()
);
#endregion
#region SearchQuery
/// <summary>
/// Compiled query for searching Employees by Name and Username
/// </summary>
protected static readonly Func<MySqlEntities, string, int, IQueryable<Employee>> SearchQuery =
CompiledQuery.Compile<MySqlEntities, string, int, IQueryable<Employee>>(
(db, search, limit) =>
(from t in db.Employees where t.Name.StartsWith(search) || t.Username.StartsWith(search) select t).Take(limit)
);
#endregion
/// <summary>
/// Select a range of Employees start at a specific offset.
/// </summary>
/// <param name="start">The starting position.</param>
/// <param name="limit">The maximum number of employees to select.</param>
/// <returns></returns>
public static List<Employee> Select(int start = 0, int limit = 10)
{
using (var db = Fx.Database)
return new List<Employee>(SelectQuery.Invoke(db, start, limit));
}
/// <summary>
/// Select a single Employee with a matching ID.
/// </summary>
/// <param name="id">The ID to search for.</param>
/// <returns></returns>
public static Employee SelectByID(int id)
{
using (var db = Fx.Database)
return SelectByIDQuery.Invoke(db, id);
}
/// <summary>
/// Select a single Employee with a matching Username.
/// </summary>
/// <param name="username">The Username to search for.</param>
/// <returns></returns>
public static Employee SelectByUsername(string username)
{
using (var db = Fx.Database)
return SelectByUsernameQuery.Invoke(db, username);
}
/// <summary>
/// Search for Employees by Name and Username.
/// </summary>
/// <param name="search">The search string.</param>
/// <param name="limit">The maximum number of Employees to select.</param>
/// <returns></returns>
public static List<Employee> Search(string search, int limit = 10)
{
using (var db = Fx.Database)
return new List<Employee>(SearchQuery.Invoke(db, search, limit));
}
/// <summary>
/// Save changes to an Employee to the database.
/// </summary>
/// <param name="employee">The Employee object to save.</param>
public static bool Save(Employee employee)
{
using(var db = Fx.Database)
{
db.Employees.Attach(employee);
db.Employees.Context.ObjectStateManager.ChangeObjectState(employee, System.Data.EntityState.Modified);
try
{
db.SaveChanges();
return true;
}
catch (Exception ex)
{
MessageBox.Show("Failed to save employee:\n\n" + ex.InnerException.Message);
return false;
}
}
}
/// <summary>
/// Add an Employee to the database.
/// </summary>
/// <param name="employee">The Employee object to add.</param>
public static bool Add(Employee employee)
{
using (var db = Fx.Database)
{
db.Employees.AddObject(employee);
try
{
db.SaveChanges();
return true;
}
catch (Exception ex)
{
MessageBox.Show("Failed to add employee:\n\n" + ex.InnerException.Message);
return false;
}
}
}
}
ここで問題は、クエリが実行されているときに例外がスローされ、その後ので、これは動作しないということである
Employee Employee = EmployeeRepository.SelectByUsername(UsernameInput.Text);
if(Employee == null || Employee.Password != PasswordInput.Password)
MessageBox.Show("Invalid login credentials.");
else
MessageBox.Show("Logged in successfully.");
...私はEmployeeRepositoryクラスを使用している方法の例だと、コンテキストを作成するときではありません。
だから私の質問....
は、どのように私は、コンテキストが作成されたときに接続エラーをキャッチし、私のカスタムエラーメッセージを表示することができます。
これを2つの質問に分けて、3番目をsuperuser.comまたはserverfault.comに投稿してください。 –
彼の質問はスーパーユーザーまたはserverfaultと何が関係していますか? – Jeff
@ JeffN825ネットワーキングに関連して、それ以前に別の質問がありました。 –