like i dislike -możliwość dodania tyklo raz dla każdego zdjęcia .Net Core

0

Witam,mam taki problem:Chciałbym żeby użytkownik mógł tylko raz dać like i dislike dla każdego zdjęcia ,obecnie każdy może dawać nieograniczoną ilość like i dislike .Ma może ktoś pomysł jak to można zrobić ?Nie chodzi mi o kod tylko podejście ,pomysł bo jak na razie to nic nie mogę wymyślić

2

No ja bym sprawdzał wcześniej czy użytkownik dał już like albo dislike :D

0

ale to chyba mało optymalne ,jak bym miał np.1000 zdjec i 100 użytkowników ,bym musiał dodać dodatlkowe pole do mojego modelu chyba np. bool czyLike i bool czyDislike ?

public partial class Memy
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [HiddenInput]
        public int Id_mema { get; set; }
        public string Autor { get; set; }
        [Required]
        public string Title { get; set; }
        [HiddenInput]
        public string coverImg { get; set; }
     
        public string Description { get; set; }
        public string Category { get; set; }
        [HiddenInput]
        public DateTime? releaseDate { get; set; }
        public DateTime? modifyDate { get; set; }
        public int? Like { get; set; }
        public int? Dislike { get; set; }
    }
6

Musisz mieć osobną tabelkę z kolumnami takimi jak IdMema, IdUsera, Like/Dislike, innego wyjścia nie ma ;)

2

A jak inaczej chcesz np wyświetlić kto dal like albo dislike, jeśli nigdzie nie zapamiętasz użytkownika?

1

Sprawdzaj tylko konkretnego użytkownika i konkretne zdjęcie, coś w stylu. Masz osobną tabelkę, jak pisał @mad_penguin.
Potem podczas ładowania zdjęcia, gdy zalogowany jest użytkownik sprawdzasz, czy ten użytkownik oceniał to zdjęcie. Cała robota.

0

zrobiłem dodatkowy model

   public class Marking
    {
        public int IdMema { get; set; }
       public string Authorr{get;set;}
        public int Like { get; set; }
        public int Dislike { get; set; }
    }

oraz metoda Like
public async Task<IActionResult> Like(int id, Marking user)
{

        System.Security.Claims.ClaimsPrincipal currentUser = this.User;
        var memy = db.Memy.SingleOrDefault(s => s.Id_mema == id);
      
        memy.Like++;
        List<Marking> ee = new List<Marking>();
        if (id != memy.Id_mema)
        {
            return NotFound();
        }
        foreach (var z in ee)
        {
            if(ModelState.IsValid && z.Authorr==currentUser.Identity.Name && z.IdMema==id && z.Like==0)
            {
               
                    z.Like = 1;
                    db.Update(memy);
                    await db.SaveChangesAsync();

                    return RedirectToAction("Show", new { id = id });
                

            }
        }
     
     
        return RedirectToAction("Show", new { id = id });
    }
ale niestety coś źle zrobiłem ,ktoś widzi błąd ?
1

To ma być inaczej...
Po załadowaniu albo przy ładowaniu mema:

  • sprawdź czy TEN użytkownik likeował TEGO mema:
select like, dislike from markings where user_id = @id_zalogowanego & mem_id = @id_mema

I teraz jeśli masz like lub dislike > 0 to nie dajesz opcji likeowania.

0

czyli pola like i dislike nie są mi potrzebne ,będe sprawdzał czy w modelu Marking w bazie znajduje się dany obraz,jeżeli tak to oznacza że like albo dislike został już podany ,tak chyba będzie lepiej ?

1

będe sprawdzał czy w modelu Marking w bazie znajduje się dany obraz,jeżeli tak to oznacza że like albo dislike został już podany

Jak jak jak? nie widzę w polu Marking żadnej informacji o tym, który user like'ował

...

Tak jak pisał @mad_penguin : Chcesz mieć model UserLikes i, analogicznie, model UserDislikes.

Pola modelu UserLikes:

  • Id usera
  • Id obrazka

Oba te pola są foreign keys. Wydaje mi się też, że możesz zrobić, by ta para była też kluczem głównym, wtedy masz od razu zagwarantowane, że nie da się wrzucić dwóch obiektów UserLikes do bazy o tym samym id usera i obrazka.

  1. Sprawdzasz, czy w bazie istnieje obiekt UserLikes o pasującym Id usera i pasującym Id obrazka
    2a. Jeśli istnieje, to znaczy, że user już raz zalajkował
    2b. Jeśli nie istnieje - to znaczy, że nie lajkował (jak zalajkuje, to wtedy wprowadzasz ten obiekt to bazy)

Do poczytania:

0

Chodzi mi o to że mój model będzie wyglądał tak

 public class Marking
    {
        [Key]
        public int IdMakring{get;set;}
        [ForeignKey("Id_mema")]
        public int IdMema { get; set; }
        [ForeignKey("Author")]
        public string Authorr {get;set;}
    
    }

nastepnie w metodzie będzie to tak :

  public async Task<IActionResult> Like(int id)
        {
            var memy = db.Memy.SingleOrDefault(s => s.Id_mema == id);
            var memyyy = db.Marking.SingleOrDefault(k => k.IdMema == id);
            System.Security.Claims.ClaimsPrincipal currentUser = this.User;
            memy.Like++;
            if (id != memy.Id_mema)
            {
                return NotFound();
            }

            if (ModelState.IsValid && memyyy.Authorr==currentUser.Identity.Name && memyyy.IdMema!=id)
            {
                memyyy.Authorr = currentUser.Identity.Name;
                memyyy.IdMema = id;
                db.Update(memy);
                await db.SaveChangesAsync();

                return RedirectToAction("Show", new { id = id });
            }
            return RedirectToAction("Show", new { id = id });
        }

       ```
czy to jest zły pomysł?
0

Ty mi powiedz, gdzie tu sprawdzasz, czy lajkujący user już nie lajkował tego mema w przeszłości? Bo nie widzę tego sprawdzania.

Tzn rozumiem, że po Twojemu Marking.Authorr to ma być user, który zalajkował? Jeśli tak, to jak zamierzasz dopuścić, by wielu userów mogło lajkować jednego mema? Na razie jak masz 2 lajki od 2 userów to Ci wyjątek będzie leciał. (Btw identyfikuj userów po ich ID a nie po ich nicku.)

Oprócz tego:

var memy = db.Memy.SingleOrDefault(s => s.Id_mema == id);
memy.Like++;
if (id != memy.Id_mema)
{
    return NotFound();
}

WTF

Czy wiesz, co robi metoda SingleOrDefault??

Do poczytania: https://docs.microsoft.com/en-us/dotnet/api/system.linq.queryable.singleordefault?view=netcore-2.2

SingeOrDefault(s => s.Id_mema == id):

  • Jeśli w bazie jest jeden i tylko jeden mem o Id_mema równym id, to go zwraca;
  • Jeśli nie ma takiego mema w bazie, to zwraca null;
  • Jeśli jest ich więcej (nie powinno tak się zdarzyć, chyba, że nachrzaniłeś z kluczami głównymi) to rzuca wyjątkiem.

Wobec tego:

memy.Like++;

Jeśli wartość parametru metody Like nie wskazuje na poprawnego mema, obrywasz wyjątkiem, ponieważ memy to null.

if (id != memy.Id_mema)
{
    return NotFound();
}

WTF - po co to sprawdzasz - użyłeś SingleOrDefault co gwarantuje Ci, że ten warunek nigdy nie będzie fałśzywy (najwyżej rzuci wyjątkiem)

I kiedy masz zwrócić NotFound() ?

Przeczytaj, co napisałem wyżej, i a) napisz poprawny warunek na NotFound i b) ustaw ten warunek w takim miejscu, by inne fragmenty kodu nie rzucały Ci wyjątkami, jeśli mema o takim id nie ma.

Poza tematem to powinieneś użyć raczej SingleOrDefaultAsync

if (ModelState.IsValid && memyyy.Authorr==currentUser.Identity.Name && memyyy.IdMema!=id)
{
   memyyy.Authorr = currentUser.Identity.Name;
   memyyy.IdMema = id;
   db.Update(memy);

WTF

Czy memyyy.Authorr jest równy currentUser.Identity.Name? Jeśli tak, to ustawmy memyyy.Authorr na currentUser.Identity.Name.

memyyy.IdMema!=id - tak jak wyżej, ten warunek NIGDY nie będzie prawdziwy, więc w ogóle Ci program NIGDY nie wejdzie do ciała ifa.

Czy Ty w ogóle myślisz, co robisz, czy działasz na zasadzie "A napiszę sobie coś, porównam losowe pole z losowym polem, może akurat zadziała"?

I inne problemy. Których już mi się nie chce opisywać.

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