11
respostas

Campo de busca não retorna valor

Em outro tópico que fiz sobre inserir valores nulos no banco por um arquivo json, alterei o modelo retirando os [Required] e fazendo uma nova migração, esse processo funcionou perfeitamente, porem quando realizo alguma pesquisa ele retorna um erro, lembrando que antes funciona normalmente a pesquisa porem com campos vazios em vez de nulos.

NullReferenceException: Object reference not set to an instance of an object.

lambda_method(Closure , Contato )
System.Linq.Utilities+<>c__DisplayClass1_0<TSource>.<CombinePredicates>b__0(TSource x)
System.Linq.Enumerable+WhereEnumerableIterator<TSource>.MoveNext()
Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider._TrackEntities<TOut, TIn>(IEnumerable<TOut> results, QueryContext queryContext, IList<EntityTrackingInfo> entityTrackingInfos, IList<Func<TIn, object>> entityAccessors)+MoveNext()
Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider+ExceptionInterceptor<T>+EnumeratorExceptionInterceptor.MoveNext()

AspNetCore.Views_Agenda_Index.ExecuteAsync() in Index.cshtml
-
            </thead>
        </table>
    </div>
    <div class="tbl-content">
        <table cellpadding="0" cellspacing="0" border="0"  class="table table-striped table-bordered">
            <tbody>
                @foreach (var contato in Model)
                {
                    <tr>
                        <th>@contato.Nome</th>
                        <td>@contato.Unidade</td>
                        <td>@contato.Departamento</td>
                        <td>@contato.Telefone</td>

Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, bool invokeViewStarts)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ActionContext actionContext, IView view, ViewDataDictionary viewData, ITempDataDictionary tempData, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor.ExecuteAsync(ActionContext context, ViewResult result)
Microsoft.AspNetCore.Mvc.ViewResult.ExecuteResultAsync(ActionContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultAsync(IActionResult result)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResultFilterAsync<TFilter, TFilterAsync>()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResultExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeResultFilters()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
11 respostas

Thiago, bom dia. Por favor coloque o código que utiliza pra fazer a pesquisa, juntamente com o código do modelo sem os [Required].

Daniel, bom dia!

AgendaController:

 public class AgendaController : Controller
    {        
        private readonly IContatoRepository contatoRepository;

        public AgendaController(IContatoRepository contatoRepository)
        {
            this.contatoRepository = contatoRepository;
        }
        public IActionResult Index(string busca)
        {
            var contato = from c in contatoRepository.GetContatos(busca)
                          where c.Unidade != null & c.Departamento != "TI"
                          & c.Departamento != "TERCEIRO"
                          orderby c.Nome ascending
                          select c;
            return View(contato);
        }
    }

AgendaModel:

 public class AgendaModel
    {
        public class BaseModel
        {
            [DataMember]
            public int Id { get; protected set; }
        }
        public class Contato : BaseModel
        {
            public Contato()
            {

            }

            public string Nome { get; private set; }

            public string Unidade { get; private set; }

            public string Departamento { get; private set; }

            public string Telefone { get; private set; }

            public string Ramal { get; private set; }

            public string Email { get; private set; }

            public Contato(string name, string office, string department, string telephonenumber, string fax, string mail)
            {
                this.Nome = name;
                this.Unidade = office;
                this.Departamento = department;
                this.Telefone = telephonenumber;
                this.Ramal = fax;
                this.Email = mail;
            }
        }
    }

ContatoRepository:

public class ContatoRepository : BaseRepository<Contato>, IContatoRepository
    {
        public ContatoRepository(ApplicationContext contexto) : base(contexto)
        {
        }

        /* Realiza a consulta na tabela do Banco de Dados */
        public IQueryable<Contato> GetContatos(string busca)
        {
            if (!string.IsNullOrEmpty(busca))
            {
                return dbSet.Where(s => s.Nome.ToLowerInvariant().Contains(busca.ToLowerInvariant())
                || s.Unidade.ToLowerInvariant().Contains(busca.ToLowerInvariant())
                || s.Departamento.ToLowerInvariant().Contains(busca.ToLowerInvariant())
                || s.Telefone.Contains(busca)
                || s.Telefone.Contains(busca)
                || s.Email.ToLowerInvariant().Contains(busca.ToLowerInvariant()));
            }

            return dbSet;
        }

        /* Valida e salva os dados do Jason no Bando de Dados */
        public void SaveContatos(List<DadosContatos> dadoscontatos)
        {
            foreach (var dado in dadoscontatos)
            {
                if (!dbSet.Where(d => d.Nome == dado.name).Any())
                {
                    dbSet.Add(new Contato(dado.name, dado.office, dado.department, dado.telephonenumber, dado.fax, dado.mail));
                }
            }
            contexto.SaveChanges();
        }
    }
    public class DadosContatos
    {
        public string name { get; set; }
        public string office { get; set; }
        public string department { get; set; }
        public string telephonenumber { get; set; }
        public string fax { get; set; }
        public string mail { get; set; }
    }

Daniel, consegue me dar esse apoio?

Thiago, perdão pela ausência.

Amanhã vou conseguir te responder com calma e ajudá-lo nessa questão, ok?

Att.

Show, obrigado pelo apoio.

Thiago, boa tarde.

O erro de NullReference está acontecendo na renderização da view. Não estou enxergando nada gritante que possa estar gerando esse problema. Única coisa diferente é que a classe Contato está aninhada dentro de AgendaModel, mas como o EF Core não reclamou na hora de fazer as migrações, tudo bem.

Uma pergunta: o SELECT é feito apenas em uma tabela? Ou seja, não é usado JOIN? Dependendo de como o join é feito, pode gerar um objeto nulo de contato. Como não vi o código do BaseRepository, não sei como está sendo gerado o dbSet. Aliás, você consegue colocar o SELECT gerado pelo EF Core nessa busca? Em geral aparece na janela de saída do AspNet Core do VS.

Vamos tentar isolar o problema: retorne para a view um select simples na tabela de contatos. Daí seguimos conversando, blz?

Abs, Daniel

Bom dia Daniel!

O SELECT é feito apenas com em uma tabela e não usa JOIN. Alterei o SELECT para buscar apenas pelo Nome e funcionou, depois fiz com Nome ou Departamento e funcionou, porem com as demais consultas não funcionou, fui testando cada um e apenas funcionou com esses.

Tive que tirar as consultas de Departamento, Telefone, Ramal e Email.

public IQueryable<Contato> GetContatos(string busca)
        {
            if (!string.IsNullOrEmpty(busca))
            {
                return dbSet.Where(s => s.Nome.ToLowerInvariant().Contains(busca.ToLowerInvariant())
                    ||s.Unidade.ToLowerInvariant().Contains(busca.ToLowerInvariant()));
            }

            return dbSet;
        }

Thiago, faz uma condição no GetContatos() verificando se Departamento, Telefone, Ramal e Email são nulos antes de usar o método da string ToLowerInvariant().

Se não rolar, acho que podemos mudar a estratégia de em vez de filtrar esses campos específicos no banco, deixar para filtrar em memória.

Daniel, notei que o erro é devido os campos estarem nulos, assim ele não consegue consultar a coluna que tem valor nulo. Alterei a forma de que os dados aparecem, para me mostrar apenas quando todos os campos estiverem preenchidos, não é o ideal mais vai me atender no momento.

Queria saber se tem alguma forma de ignorar os campos nulos durante a consulta.

Thiago, boa tarde. O Daniel irá responder em seguida.

Fala, Thiago, tudo bem?

Entendi que você deseja consultar um campo que pode estar nulo ou não, certo? Inclusive fazendo isso no banco né.

Eu usaria uma condição que levasse em conta as duas situações:

( (s.Unidade == null) || (s.Unidade.
  ToLowerInvariant()
  .Contains(busca)))

Algo mais ou menos assim.

Uma pergunta: porque você está usando Contato como uma classe aninhada de AgendaModel? Algum motivo em especial?

Abs.