dziwne zachowanie przy dodawaniem danych do bazy

0

mam problem z dodawaniem obiektu takiej klasy do bazy danych:

public class EatenMeal
{
    public int Id { get; set; }
    public double Serving { get; set; }
    public string Username { get; set; }
    public DateTime Date { get; set; }
    public virtual Meal Meal { get; set; }
    public virtual MealType MealType { get; set; }
}
 

Jeszcze kawałek kontrolera

 
var meal = mealRepository.GetMeal(model.MealId);
EatenMeal eatenMeal = new EatenMeal()
{
    Meal = meal,
    Serving = model.Serving,
    Username = User.Identity.Name,
    MealType = mealTypeRepository.GetMealType(model.MealTypeID),
    Date = model.Date
};
eatenMealRepository.AddEatenMeal(eatenMeal);

Mianowicie problem jest taki, że w bazie danych pojawia się nowy rekord, ale pola Meal_MealId oraz MealType_Id mają wartości całkiem inne niż, te który powinny być. eatenMeal.Meal.MealId oraz eatenMeal.MealType.Id w trybie debugowania do samego końca mają wartości, które zostały nadane w kontrolerze, natomiast w bazie danych wspomniane wyżej pola przyjmują wartości, które odpowiadają numerowi ID w ich tabelach. Czyli jak w bazie Meals mam 1000 rekordów i w MealTypes 5, to w tabeli EatenMeals pola Meal_MealId oraz MealType_Id dostają kolejno wartości 1001 i 4. Dlaczego tak się dzieje? Meal_MealId powinno być równe id obiektu meal pobranego z repozytorium, a następnie przypisanego do właściwości Meal w obiekcie eatenMeal, podobnie z MealType...

Na koniec jeszcze mogę podać definicje tabeli, ale w niej wszystko powinno być ok

CREATE TABLE [dbo].[EatenMeals] (
    [Id]          INT            IDENTITY (1, 1) NOT NULL,
    [Serving]     FLOAT (53)     NOT NULL,
    [Username]    NVARCHAR (MAX) NULL,
    [Date]        DATETIME       NOT NULL,
    [Meal_MealId] INT            NULL,
    [MealType_Id] INT            NULL,
    CONSTRAINT [PK_dbo.EatenMeals] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_dbo.EatenMeals_dbo.Meals_Meal_MealId] FOREIGN KEY ([Meal_MealId]) REFERENCES [dbo].[Meals] ([MealId]),
    CONSTRAINT [FK_dbo.EatenMeals_dbo.MealTypes_MealType_Id] FOREIGN KEY ([MealType_Id]) REFERENCES [dbo].[MealTypes] ([Id])
);


GO
CREATE NONCLUSTERED INDEX [IX_Meal_MealId]
    ON [dbo].[EatenMeals]([Meal_MealId] ASC);


GO
CREATE NONCLUSTERED INDEX [IX_MealType_Id]
    ON [dbo].[EatenMeals]([MealType_Id] ASC);

W załączniku zrzut ekranu z momentu dodawania danych do bazy. Widać z MealId = 1, a w rekordzie w kolumnie Meal_MealId pojawiło się 1001, gdyż wcześniej miałem w tabeli Meals 1000 rekordów.

0

Uzywasz indexow, sprawdz jakie one maja wartosci, to nie dziala tak ze jezeli usuniesz te 1000 rekordow to index sie cofnie. Zapewne musisz zresetowac index.

0

ale to nie o to chodzi. po zresetowaniu indeksów zapewne dodanie nowego obiektu eatenMeal do bazy spowoduje, że kolumna Meal_MealId będzie miała wartość 1, a mam mieć wartość id takiego posiłku jaki jest pobierany z repo do obiektu meal, a później przypisywany do właściwości Meal w obiekcie eatenMeal.

0

Czyli zamiast edycji rekordów następuje dodanie?
To chyba podobny problem do tego: Jak poprawnie aktualizować obiekty w bazie

0

no ale u mnie te właściwości w klasie są ustawione jako virtual, akurat nie w poście otwierającym temat, bo przez przypadek skopiowałem nie ten kod.

Moje encje:

    public class Meal
    {
        public int MealId { get; set; }
        public string Name { get; set; }
        public double Protein { get; set; }
        public double Carbohydrates { get; set; }
        public double Fat { get; set; }
        public double Calories { get; set; }
    }
public class MealType
{
    public int MealTypeId { get; set; }
    public string Name { get; set; }
}
public class EatenMeal
{
    public int Id { get; set; }
    public double Serving { get; set; }
    public string Username { get; set; }
    public DateTime Date { get; set; }
    public virtual Meal Meal { get; set; }
    public virtual MealType MealType { get; set; }
}

EatenMealViewModel:

public class EatenMealVM
{
    public int MealId { get; set; }
    [Display(Name = "Nazwa posiłku")]
    public string MealName { get; set; }
    [Display(Name = "Typ posiłku")]
    [Required(ErrorMessage = "Proszę wybrać typ posiłku")]
    public int MealTypeID { get; set; }
    [Display(Name = "Porcja (g)")]
    [Required(ErrorMessage = "Proszę podać ilość spożywanej porcji.")]
    [Range(0.00, double.MaxValue, ErrorMessage = "Proszę podać dodatnią ilość.")]
    public double Serving { get; set; }
    [Display(Name = "Data spożycia")]
    [Required(ErrorMessage = "Proszę podać datę spożycia")]
    [DataType(DataType.Date)]
    public DateTime Date { get; set; }
    public SelectList MealTypeList { get; set; }
}

Tabela Meals w bazie danych na aktualny moment posiada 1000 wierszy, a MealTypes 4.

Chcąc dodać zjedzony posiłek do dziennika, wchodzę w listę posiłków. Wyświetla mi się tych 1000 pozycji. Wybieram jedną przez opcję "Dodaj". Przechodzę do akcji CreateEatenMeal w kontrolerze EatenMealController

public ActionResult CreateEatenMeal(int id)
{
    var meal = mealRepository.GetMeal(id);
    List<MealType> mealTypes = new List<MealType>();
    mealTypes = mealTypeRepository.GetMealTypes();
    EatenMealVM model = new EatenMealVM()
    {
        MealId = meal.MealId,
        MealName = meal.Name,
        MealTypeList = new SelectList(mealTypes, "Id", "Name")
    };
    return View(model);
}

Przechodzę do widoku, w którym widnieje nazwa posiłku, który wybrałem do dodania, uzupełniam formularz wpisując porcję, datę oraz typ posiłku. Po czas na metodę POST.

[HttpPost]
public ActionResult CreateEatenMeal(EatenMealVM model)
{
    if (ModelState.IsValid)
    {
        EatenMeal eatenMeal = new EatenMeal()
        {
            Meal = mealRepository.GetMeal(model.MealId);,
            Serving = model.Serving,
            Username = User.Identity.Name,
            MealType = mealTypeRepository.GetMealType(model.MealTypeID),
            Date = model.Date
        };
        eatenMealRepository.AddEatenMeal(eatenMeal);
        return RedirectToAction("Index", "Home");
    }
    else
    {
        List<MealType> mealTypes = new List<MealType>();
        mealTypes = mealTypeRepository.GetMealTypes();
        model.MealTypeList = new SelectList(mealTypes, "Id", "Name");
        return View(model);

    }
}

Tworzę obiekt klasy EatenMeal i inicjuje go odpowiednim wartościami i dodaje go do bazy przez repozytorium. Więc dajmy na to na początku w liście posiłków wybrałem posiłek z 1 pozycji. Jego ID to 1. Przeszedłem do widoku dodawania tego posiłku do bazy posiłków zjedzonych. Uzupełniam porcję, datę oraz wybieram typ posiłku, np śniadanie czyli ID również 1. I w trybie debugowania już w samej metodzie repozytorium obiekt eatenMeal w właściwości Meal ma ID równe 1, a w właściwości MealType ID też równe 1. Czyli wydaje się, że jest wszystko ok, mimo to, gdy wchodzę do bazy danych, żeby podejrzeć dodany rekord to zgadza się Id, Serving, Date, Username, ale pola Meal_MealId oraz MealType_Id mają wartość odpowiednio 1001 i 5. A nie 1 i 1. Wchodzę do tabeli Meals i widzę, że dodał się nowy posiłek a w tabeli MealTypes nowy typ posiłku o tych ID: 1001 i 5

tabele: http://pastebin.com/Yzc2yZQp

ok udało mi się znaleźć rozwiązanie

 
public void AddEatenMeal(EatenMeal eatenMeal)
{
     context.Meals.Attach(eatenMeal.Meal);
     context.MealTypes.Attach(eatenMeal.MealType);
     context.EatenMeals.Add(eatenMeal);
     context.SaveChanges();
}

@somekind mógłbyś coś napisać na ten temat? :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1