Je souhaite créer un bouton de recherche qui permettrait à un utilisateur de rechercher un membre et de charger les détails associés. J'utilise également Ajax BeginForm.

Il y a 3 classes / tables:

    public Book()
    {
        this.Loans = new HashSet<Loan>();
    }

    public int ISBN { get; set; }
    public string Name { get; set; }
    public string Author { get; set; }

    public int OnLoan { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Loan> Loans { get; set; }
}
   Loan Class
  public partial class Loan
{
    public int LoanId { get; set; }
    public System.DateTime CheckOutDate { get; set; }
    public System.DateTime ReturnDate { get; set; }
    public decimal FinePrice { get; set; }
     public Nullable<int> MemberId { get; set; }
    public Nullable<int> ISBN { get; set; }

    public virtual Book Book { get; set; }
    public virtual Member Member { get; set; }
}

Classe de membre:

  public partial class Member
    {
        public Member()
        {
            this.Loans = new HashSet<Loan>();
        }

        public int MemberId { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public string PostCode { get; set; }
        public int TelNo { get; set; }


        public virtual ICollection<Loan> Loans { get; set; }
    }

Dans mon contrôleur BHistory:

public ActionResult HistorySearch(string qh)
{
    var history = Gethistory(qh);

    return PartialView(history);


}
private List<Loan> Gethistory(string searchString)
{
    return db.Loans
        .Where(a => a.MemberId.ToString().Contains(searchString) && a.Book.OnLoan == 1)
       .ToList();
}

Donc, au moment où la recherche fonctionne correctement, elle renvoie le résultat correct, dans le navigateur l'utilisateur entre memberid et une liste de résultats apparaît. Cependant, je veux seulement que le dernier des résultats apparaisse. Pas une liste de résultats

Donc au lieu d'utiliser ToList (), je veux utiliser LastorDefault (), mais j'obtiens le message d'erreur: impossible de convertir Models.Loan en collections.generic.list.

J'ai donc édité la méthode d'action

private Loan Gethistory(string searchString)
    {
        return db.Loans
            .Where(a => a.MemberId.ToString().Contains(searchString) && a.Book.OnLoan == 1)
           .LastorDefault();

Cependant, lorsque je l'exécute, j'obtiens le message d'erreur:

LINQ to Entities ne reconnaît pas la méthode 'Library1.Models.Loan LastOrDefaultLoan', et cette méthode ne peut pas être traduite en une expression de magasin.

En conclusion, comment puis-je faire apparaître le dernier des résultats, pas une liste.

Cette question est différente des questions qui font référence aux réponses avec l'utilisation de Last () ou LastorDefault () car ici même si nous passons à l'utilisation de OrderByDescending () et First () ou FirstorDefault (), la réponse / résultat ne fonctionnerait pas. L'erreur résidait également dans la possibilité de renvoyer une liste même lorsque je pensais que la réponse ne devrait pas renvoyer une liste

Merci

0
Sam 1 août 2017 à 15:32

2 réponses

Meilleure réponse

Le problème est que le modèle sur votre page recherche un List<Loan>, et vous ne lui envoyez qu'un Loan. Au moment où j'ai publié cette réponse, vous n'avez pas votre méthode de contrôleur ou votre vue dans le cadre de votre question, je changerais donc votre requête comme suit:

private List<Loan> Gethistory(string searchString)
{
    var loan = db.Loans
                 .Where(a => a.MemberId
                              .ToString()
                              .Contains(searchString) && 
                             a.Book.OnLoan == 1)
                 .OrderByDescending(a => a.LoanId)
                 .FirstOrDefault();

    return new List<Loan> { loan };
}

Comme Stefan l'a dit dans sa réponse, SQL n'a pas de méthode LastOrDefault, vous devez donc écrire votre requête d'une manière qui soit plus facile pour EF à convertir en SQL.

Alternativement, vous pouvez changer votre vue pour avoir un modèle qui est un seul prêt, bien que cela rendrait la grille (présumée) que vous les affichez / elle un peu moins intuitive.

3
krillgar 1 août 2017 à 12:43

Essaye ça:

 return db.Loans
        .Where(a => a.MemberId.ToString().Contains(searchString) && a.Book.OnLoan == 1)
        .OrderByDescending(c => c.MemberId)
        .FirstOrDefault();

SQL ne comprend pas LastOrDefault

Vous devrez donc commander la liste. En utilisant OrderByDescending, vous inverserez cet ordre et, par conséquent, pourrez prendre le meilleur record.

Si vous souhaitez toujours transmettre une collection, vous pouvez également utiliser le OrderByDescending

return db.Loans
        .Where(a => a.MemberId.ToString().Contains(searchString) && a.Book.OnLoan == 1)
        .OrderByDescending(c => c.MemberId);

Voir LINQ To Entities ne reconnaît pas la méthode Last. Vraiment? pour plus de détails.

Ou cette question similaire:

supprimer un enregistrement avec un enfant

1
Stefan 1 août 2017 à 12:51