什么是配置表适配器和数据集的正确方法?

时间:2012-10-24 13:02:22

标签: c# database idisposable

我一直在研究一个使用表适配器和数据集来访问访问数据库的项目。我已经接近完成并从visual studio运行代码分析,它出现了一些关于需要在我使用这些方法的特定类上实现IDisposable的错误。虽然我已经看了一些关于使用dispose方法或使用using块的不同内容,但我不确定如何使这个工作。数据集和表适配器被创建为全类使用的全局变量,许多类将调用其他类,这些类也将使用不同的表适配器和数据集。我已经尝试创建一个Dispose方法,但我不知道何时调用它,我想知道是否在错误的时间调用它会导致我的程序崩溃。以下是我需要实现Idisposable的其中一个类的示例:

   using System;
   using System.Collections.Generic;
   using System.Linq;
    using System.Text;

 namespace recipeDataBase 
 {
     class NewRecipe : IDisposable
     {
         recipiesNewDataSet recipeDataSet = new recipiesNewDataSet();
         recipiesNewDataSetTableAdapters.RecipeTableAdapter recipeTableAdapter = new      recipiesNewDataSetTableAdapters.RecipeTableAdapter();
    recipiesNewDataSetTableAdapters.RecipeIngredientTableAdapter recipeIngredientTableAdapter = new recipiesNewDataSetTableAdapters.RecipeIngredientTableAdapter();
    recipiesNewDataSetTableAdapters.RatingTableAdapter ratingTableAdapter = new recipiesNewDataSetTableAdapters.RatingTableAdapter();
    recipeDataBase.recipiesNewDataSetTableAdapters.IngredientTableAdapter ingredientTableAdapter = new recipiesNewDataSetTableAdapters.IngredientTableAdapter();
    private RecipeInfo newRecipe;
    private RatingNum originalRatingNum;
    private RatingNum newRating;
    private RecipeInfo originalRecipe;
    private string[] ingredients;

    public NewRecipe(RecipeInfo incommingNewRecipe, RatingNum IncommingNewRating, string[] incommingIngredients)
    {
        newRecipe = incommingNewRecipe;
        newRating = IncommingNewRating;
        ingredients = incommingIngredients;
        CreateNewRecipe();
        UpdateNewRecipe();
    }
    public void CreateNewRecipe()
    {
        originalRatingNum = new RatingNum();
        originalRecipe = new RecipeInfo();
        originalRatingNum.cookingTime = 0;
        originalRatingNum.easeOfCooking = 0;
        originalRatingNum.familyRating = 0;
        originalRatingNum.healthRating = 0;
        originalRatingNum.userRating = 0;

        ratingTableAdapter.Fill(recipeDataSet.Rating);
        ratingTableAdapter.Insert(originalRatingNum.userRating, originalRatingNum.familyRating, originalRatingNum.healthRating, originalRatingNum.easeOfCooking, originalRatingNum.cookingTime);
        Query getNewRecipeNumbers = new Query();
        int newRatingNumber = getNewRecipeNumbers.newRatingNum();



        originalRatingNum.ratingNum = newRatingNumber;
        newRating.ratingNum = newRatingNumber;
        newRecipe.ratingNum = newRatingNumber;
        originalRecipe.recipeName = "newRecipe";
        originalRecipe.nationality = "newRecipe";
        originalRecipe.recipeEvent = "newRecipe";
        originalRecipe.source = "newRecipe";
        originalRecipe.type = "newRecipe";
        originalRecipe.servings = "0";
        originalRecipe.ratingNum = newRatingNumber;


        recipeTableAdapter.Fill(recipeDataSet.Recipe);
        recipeTableAdapter.Insert(originalRecipe.recipeName, originalRecipe.nationality, originalRecipe.recipeEvent, originalRecipe.source, originalRecipe.type, originalRecipe.servings, originalRecipe.ratingNum); 
        int newRecipeNum = getNewRecipeNumbers.newRecipeNum();
        newRecipe.recipeNum = newRecipeNum;
        originalRecipe.recipeNum = newRecipeNum;
        recipeDataSet.AcceptChanges();
    }

    public void UpdateNewRecipe()
    {
        UpdateRatingNum updateRatingNum = new UpdateRatingNum(originalRatingNum, newRating);
        UpdateRecipe updateRecipe = new UpdateRecipe(newRecipe, originalRecipe);

        UpdateIngredients updateIngredients = new UpdateIngredients(ingredients);
        UpdateRecipeIngredient updateRecpeIngredients = new UpdateRecipeIngredient(ingredients, newRecipe.recipeNum);
        recipeDataSet.AcceptChanges();

    }


    public void Dispose()
    {
        ratingTableAdapter.Dispose();
        recipeTableAdapter.Dispose();
        recipeTableAdapter.Dispose();
        ingredientTableAdapter.Dispose();
        recipeDataSet.Dispose();
        throw new NotImplementedException();
    }
}

}

正如您所看到的,我确实实现了Idisposable并使用自动创建的方法将所有表适配器和数据集放在那里进行处置,但是如何使用它以及在哪里使用?

感谢您的帮助

克雷格

3 个答案:

答案 0 :(得分:2)

正常模式:

using (var nr = new NewRecipe() )
{
   ...
}

但这里有一些注意事项:

  • DataSet和DataAdapter上的IDisposable接口是假人,跳过它们时不会损失太多。
  • 您的类具有Repository和Domain对象的双重角色。考虑将其分为两类。

答案 1 :(得分:1)

正如其他答案中所提到的,实现IDisposable的对象用法的正确方法是使用如下的使用块:

using (var recipe = new NewRecipe())
{
    //put your code that uses recipe here
}

我想指出的是IDisposable模式的正确实现。请注意,MSDN article for the IDisposable interface上有一个完整的示例。

class Recipe : IDisposable
{
    bool isDisposed = false;
    TableAdapter myDisposableMember;

    public void Dispose()
    {
        Dispose(true);
        GC.SupressFinalize(this);
    }

    public virtual Dispose(bool isDisposing)
    {
        if (!isDisposed) //only clean up once
        {
            //clean up unmanaged resource here
            //in this case we don't have any

            //clean up managed resources (IE those that implemetn IDisposable only if
            //Dispose() was called (not the case when invoked during finalisation)
            if (isDisposing)
            {
                if(myDisposableMember == null)
                {
                    myDisposableMember.Dispose()
                    myDisposablemember = null;
                }
            }

            //mark this instance as cleaned up
            isDisposed = true;
        }
    }

    //if our class has any unmanaged resources you implement a destructor to guarantee
    //that they're freed. We don't have any here so we don't implement it.
    //~Recipe()
    //{
    //    Dispose(false);
    //}
}

另请注意,在最终确定期间不应抛出异常(IE:~Recipe())。因此Dispose(bool)不应该抛出异常。

答案 2 :(得分:0)

正确的使用方式是using。只是不要把它拿在手里 -

using(DataAdapter ratingTableAdapter = new DataAdapter())
{

}
一旦代码从使用块中出来,

ratingTableAdapter 就会被处理掉。