Autocompletador con Entity Framework

En este tutorial crearemos un elemento web que contenga un autocompletador de datos extraidos de WCF (JSON) que se almacenarán en la entidad seleccionada a través EntityFramework. ¿Por qué os traigo este tutorial? Os cuento... Mi problema surgió porque no pude encontrar un control que se encargara de las entidades, las cuales necesitaba para seleccionar datos de una lista y ser capaz de almacenarlos en forma de entidad. Encontré algunos ejemplos en la red, pero ninguno de ellos cumplía con el ciclo de almacenamiento de la entidad, por lo que no tuve otra opción que construirlo desde cero. También necesitaba otra característica, que pudiera ser utilizado en un gridview para su edición. El problema actual con un combobox es que al cargar la página, se cargan necesariamente todos los datos. El control de búsqueda está optimizado para responder a través de (JSON), así como la consulta (LINQ - AsNoTracking - AsParallel).

Utilizaremos...

  • Visual Studio 2013 - Update 5
  • AjaxControlToolkit versión=15.1.4.0
  • EntityFramework versión=6.1.3
  • jQuery versión=2.1.4
  • Newtonsoft.Json versión=7.0.1
  • Windows Communication Foundation

Cómo llevarlo a cabo...

Cuando el control se ha inicializado, cargamos dinámicamente los archivos JavaScript a los eventos OnClientPopulating, OnClientHiding, OnClientPopulated, OnClientItemSelected.

Private Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init

        Dim Evento_OnClientPopulating As String
        Dim Evento_OnClientCompleted As String
        Dim Evento_OnClientPopulated As String
        Dim Evento_OnClientItemSelected As String

        Evento_OnClientPopulating = _
        Me.AutoCompleteExtenderClients.ClientID + "_OnClientPopulating"

        Evento_OnClientCompleted = _
        Me.AutoCompleteExtenderClients.ClientID + "_OnClientCompleted"

        Evento_OnClientPopulated = _
        Me.AutoCompleteExtenderClients.ClientID + "_OnClientPopulated"

        Evento_OnClientItemSelected = _
        Me.AutoCompleteExtenderClients.ClientID + "_OnClientItemSelected"

        AutoCompleteExtenderClients.OnClientPopulating = _
        Me.AutoCompleteExtenderClients.ClientID + "_OnClientPopulating"

        AutoCompleteExtenderClients.OnClientHiding = _
        Me.AutoCompleteExtenderClients.ClientID + "_OnClientCompleted"

        AutoCompleteExtenderClients.OnClientPopulated = _
        Me.AutoCompleteExtenderClients.ClientID + "_OnClientPopulated"

        AutoCompleteExtenderClients.OnClientItemSelected = _
        Me.AutoCompleteExtenderClients.ClientID + "_OnClientItemSelected"

        ScriptManager.RegisterClientScriptBlock(Me, Me.GetType(), _
        Evento_OnClientPopulating, Me.OnClientPopulating(Evento_OnClientPopulating), False)

        ScriptManager.RegisterClientScriptBlock(Me, Me.GetType(), _
        Evento_OnClientCompleted, Me.OnClientCompleted(Evento_OnClientCompleted), False)

        ScriptManager.RegisterClientScriptBlock(Me, Me.GetType(), _
        Evento_OnClientPopulated, Me.OnClientPopulated(Evento_OnClientPopulated), False)

        ScriptManager.RegisterClientScriptBlock(Me, Me.GetType(), _
        Evento_OnClientItemSelected, Me.OnClientItemSelected(Evento_OnClientItemSelected), False)

End Sub

El control TextBox está asociado con el control AjaxToolKit:AutocompleteExtender y configurado para los web services usando WCF. El control Asp:HiddenField es utilizado para almacenar la entidad serializada seleccionada.

 
<asp:textbox autocompletetype="Search" 
autopostback="false" id="txtClient" maxlength="40" 
ontextchanged="txtClient_TextChanged" runat="server"></asp:textbox>                   

<asp:hiddenfield id="hdnValue" 
onvaluechanged="hdnValue_ValueChanged" runat="server">
</asp:hiddenfield>

<ajaxtoolkit:autocompleteextender 
completioninterval="3" 
completionlistcssclass="completionList" 
completionlisthighlighteditemcssclass="itemHighlighted" 
completionlistitemcssclass="listItem" 
completionsetcount="20" 
delimitercharacters="" 
enablecaching="false" 
firstrowselected="true" 
id="AutoCompleteExtenderClients" 
minimumprefixlength="1" 
runat="server" 
servicemethod="GetClientsWCF" 
servicepath="~/ServicesWCF/Services.svc" 
targetcontrolid="txtClient" 
usecontextkey="true">
</ajaxtoolkit:autocompleteextender>

Para buscar los datos en la lista, introduce el parámetro prefixText y luego ejecuta la consulta LINQ. Una vez que la consulta se haya completado, serializa los datos y luego envía el Id y el Name al cliente.

Public Function GetClientsWCF(ByVal prefixText As String, ByVal count As Integer, _
	ByVal contextKey As String) As IEnumerable(Of Object) Implements IServices.GetClientsWCF
       
   Using ContextUOWork As New DatabaseEntities

		Try

			Dim AgentesRequest As New ConcurrentBag(Of Object)

			ContextUOWork.Database.Connection.Open()
			Dim query As List(Of Names) = (From p In ContextUOWork.Names.AsNoTracking _
				Where (p.Name.Trim.ToUpper.StartsWith(prefixText.Trim.ToUpper)) _
				Take count Order By p.Name Ascending).AsParallel.ToList()
			ContextUOWork.Database.Connection.Close()

			For Each c As Names In query

				AgentesRequest.Add(_json.Serialize(New With { _
								Key .Id = c.Id, _
								Key .Name = c.Name.Trim.ToUpper()
									 }))
			Next

			Return AgentesRequest.Reverse.Cast(Of Object)()

		Catch ex As Exception

			Throw New Exception("GetClientsWCF")

		End Try

	End Using

 End Function

Los datos se muestran en el cliente mediante la ejecución del código JavaScript creado en el paso 1. Hago el análisis de los datos JSON.parse (list.childNodesi.value) para transformar y ser capaz de leerlos desde el cliente en mi lista.

function Clients_AutoCompleteExtenderClients_OnClientPopulated(sender, e)
{
    $('#Clients_txtClient').removeClass('loading');
    var list = $find('Clients_AutoCompleteExtenderClients').get_completionList();
    var count = list.childNodes.length;
    list.childNodes;
    for (i = 0; i < count; i++) {
    var item = JSON.parse(list.childNodes[i]._value);
    var Id = item.Id.toString().rpad('u00a0',10);
    var Name = item.Name.toString().rpad('u00a0',50);
    list.childNodes [i].innerHTML = Id + Name;};
};

Para seleccionar los datos en la lista, es serializado y almacenado en la variable oculta (Clients_hdnValue), y luego hacemos la devolución de datos al servidor (doPostBack) para ejecutar el evento hdnValueValueChanged.

function Clients_AutoCompleteExtenderClients_OnClientItemSelected(sender, e) {
     var selectedAgente = eval('(' + e._value + ')');
     $('#Clients_txtClient').val(selectedAgente.Name);
     $('#Clients_hdnValue').val(JSON.stringify(selectedAgente));
     __doPostBack('Clients_hdnValue', '')
 };

Deserializa el valor que está en el campo de tipo HiddenField y dispara el control de eventos ClientSelected() para advertir que se selecciona una entidad.

Protected Sub hdnValue_ValueChanged(sender As Object, e As EventArgs) Handles hdnValue.ValueChanged

    NameTyped = New JavaScriptSerializer().Deserialize(Of Object)(DirectCast(sender, HiddenField).Value)

    For Each prop As System.Reflection.PropertyInfo In _NamesEF.GetType().GetProperties()
        If prop.CanRead Then
            For Each pair In NameTyped
                If pair.Key.Equals(prop.Name) Then
                    prop.SetValue(_NamesEF, pair.Value, Nothing)
                End If
            Next
        End If
    Next
       
    Me.TBL_NAMES = _NamesEF

    RaiseEvent ClientSelected()

End Sub

El formulario WebForm.aspx detecta el evento del crontol (clientes). La propiedad TBLNAMES contiene la entidad seleccionada.

Private Sub Clients_ClientSelected() Handles Clients.ClientSelected
    Id1.Text = Me.Clients.TBL_NAMES.Id
    Name1.Text = Me.Clients.TBL_NAMES.Name
    UpdatePanel_Data.Update()
End Sub

Y este ha sido el tutorial sobre crear un autocompletador con EntityFramework, esperamos que te haya gustado y sepas aplicarlo en tus futuros proyectos. Ya sabes que si nos quieres proponer un tema que quieres ver reflejado como un tutorial o como una práctica, solo tienes que hacer uso del área de comentarios de un poco más abajo. Por el contrario, si quieres enviarnos tus propios tutoriales, puedes hacerlo a través de la intranet de usuarios que está habilitada para ello, a través del menú Enviar Tutorial. Ya sabes, ayúdanos a crecer con tus conocimientos. ¡Un saludo y feliz código!

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
SIGUIENTE ARTÍCULO