Inner Join y select de más de un objeto en LinQ

No hay mucho que decir al respecto, como hacer inner joins y seleccionar varias tablas en la parte select

 
public Rule GetRule(string sEventCode, string sActionClassName, string sActionMethodName) 
		{
            //select distinct * from ers_action
            //inner join ers_rule on ersr_ers_action_fk = ersa_id
            //inner join ers_event on erse_id = ersr_ers_event_fk
            //where erse_code like 'com_recalculate_shopping_cart' and ers_action.instance_id = 402473
 
            var Resultado = (from oRule in Database.AppDataContextLinq.ers_rule_linq
                            join oAction in Database.AppDataContextLinq.ers_action_linq on oRule.ersr_ers_action_fk   equals oAction.ersa_id 
                            join oEvent in Database.AppDataContextLinq.ers_event_linq on oRule.ersr_ers_event_fk equals oEvent.erse_id
                            where oAction.ersa_method_name == sActionClassName &&
                            oAction.ersa_class_name == sActionClassName &&
                            oEvent.erse_code == sEventCode &&
                            oEvent.instance_id == oRule.instance_id && oAction.instance_id == oRule.instance_id &&
                            oRule.instance_id ==AppUtils.GetInstanceId(Database )
                            select new {Reglas = oRule , Acciones = oAction, Eventos = oEvent}).SingleOrDefault();
 
 
            Core.ERS.Beans.Rule _Rule = new Core.ERS.Beans.Rule( Resultado.Reglas);
            _Rule.Action = new Core.ERS.Beans.Action(Resultado.Acciones);
            _Rule.Event  = new Core.ERS.Beans.Event(Resultado.Eventos);
 
            return _Rule;
		}

Como realizar un where condicional con LinQ

Muchas veces nos vemos perdidos con LinQ cuando traducimos consultas ya hechas.
En este caso estaba migrando un código que generaba SQL condicional en función de las variables que recibía, lo cierto es que la solución de de lo más tonto.
Como LinQ no se ejecuta hasta que haces un ToList() o un FirsItemOrDefault, vamos hasta que traes algún dato, esto te permite jugar con la query sin interaccionar con la base de datos.

Perdonar las funciones completas pero como siempre voy sin tiempo.

        public RootBeanList GetActive(string sLangId, bool bDefaultFirst)
        {
            try
            {
                Language oBean = new Language();
                Logger.Instance.LogMsg(LoggingLevelsEnum.DEBUG, "Buscando idiomas activos");
 
                List oList;
 
                var oConsulta = from oItem in Database.AppDataContextLinq.language_linq
                                where oItem.lang_active == true &&
                                oItem.instance_id == (int?)AppUtils.GetInstanceId(Database)
                                select oItem;
 
                if (!string.IsNullOrEmpty(sLangId))
                    oConsulta = oConsulta.Where(p => p.lanl_language_fk  == sLangId);
                else
                    oConsulta = oConsulta.Where(p => p.lanl_language_fk == "es");
 
                oConsulta = oConsulta.OrderByDescending (m=> m.lang_default);
 
                oList = oConsulta.ToList();
 
                return RootBeanList.LinqToRootBeanList(oList, oBean);
 
            }
            catch (Exception ex)
            {
                Logger.Instance.LogMsg(LoggingLevelsEnum.ERROR, "Error buscando por Idioma: " + sLangId, ex);
                return null;
            }
        }
 
 public static RootBeanList LinqToRootBeanList(List Lista, D ItemBean)
        {
            RootBeanList oList = new RootBeanList();
 
            if (Lista == null) return null;
 
            foreach (T extraItem in Lista)
            {
                RootBean oItem = (RootBean)Activator.CreateInstance(ItemBean.GetType(),extraItem);                
                oList.Add(oItem);
            }
            return oList;
        }

Otra de las cosas que quería compartir aunque no es ningún descubrimiento es la forma de hacer un “in” de SQL.

int[] aiContinentId={3,14,25,99,101}
 
public RootBeanList GetListByContinents(int[] aiContinentId, string sLngId, RootBean oBean) 
		{
            try
            {
                if (aiContinentId != null && aiContinentId.Length > 0 )
                {
 
                    List output = new List();
 
                    for (int i = 0; i < aiContinentId.Length; i++)
                        output.Add (aiContinentId[i]);
 
                    List oList = (from item in Database.AppDataContextLinq.country_linq
                                                where <strong>output.Contains (item.ctry_continent_fk) &amp;&amp; </strong>
                                                item.ctlg_language_fk ==sLngId &amp;&amp;
                                                item.instance_id == (int?)AppUtils.GetInstanceId(Database)
                                                orderby item.ctlg_name
                                                select item).ToList();
 
                    return RootBeanList.LinqToRootBeanList(oList, (Country)oBean);
                }
                return null;
            }
            catch (Exception ex)
            {
                Logger.Instance.LogMsg(LoggingLevelsEnum.ERROR, "Error buscando Pais por Continente ", ex);
                return null;
            }
		}

Reducir carga del servidor asignando prioridades en procesos

Tal y como reza el título  si se reasigna el orden de prioridad que tiene cada proceso, se puede reducir la carga del servidor.

El problema: linux tiene niveles de prioridad para todas las tareas, estas prioridades van desde -20 a +19, 0 es el valor por defecto para todos los procesos. Como te habrás dado cuenta si todos los procesos tiene 0 están peleándose entre ellos por los recursos.

Como siempre los chicos de R-fx networks creadores de APF y BFD entre otros han creado un script para tal fin, SPRI del acronim System Priority.

El instalarlo es sencillo, descomprimir y lanzar el script install.sh tras instalarlo, te añadirá una tarea en el cron (/etc/cron.d/spri) cada 45 minutos..

wget http://www.rfxn.com/downloads/spri-current.tar.gz

tar xzf spri-current

cd spri-current

./install.sh

Después de esto encontrarás los siguientes ficheros en /usr/local/spri o haz un whereis spri para encontrarlos.
La cosa es tan sencilla como editar los ficheros high, med y low para asignar prioridades a los procesos según se quiera.

Esta es la configuración de un servidor en producción

[root@srv01 prios]# cat high
httpd
[root@srv01 prios]# cat low
clamav
httpsd
freshclam
python2.2
clamd
mysqld
spamd
spamassassin
mysqld-max
[root@srv01 prios]# cat low-med
qmail-send
qmail-remote
[root@srv01 prios]# cat med
MailScanner
[root@srv01 prios]# cat med-high
php

Salida del script

[root@srv01 prios]# /usr/local/sbin/spri -v
SPRI 0.5 [spri@r-fx.org]
========================
list file '/usr/local/spri/prios/rt' appears empty, nothing done for PRIO -2.
 
Setting httpd to priority 4:
6975: old priority 4, new priority 4
13028: old priority 4, new priority 4
13165: old priority 4, new priority 4
13561: old priority 4, new priority 4
13608: old priority 4, new priority 4
13725: old priority 4, new priority 4
13852: old priority 4, new priority 4
14278: old priority 4, new priority 4
14348: old priority 4, new priority 4
14352: old priority 4, new priority 4
14406: old priority 4, new priority 4
14407: old priority 4, new priority 4
14409: old priority 4, new priority 4
14767: old priority 4, new priority 4
14800: old priority 4, new priority 4
14808: old priority 4, new priority 4
14809: old priority 4, new priority 4
14811: old priority 4, new priority 4
14814: old priority 4, new priority 4
14871: old priority 4, new priority 4
14887: old priority 4, new priority 4
14890: old priority 4, new priority 4
14891: old priority 4, new priority 4
14892: old priority 4, new priority 4
14895: old priority 4, new priority 4
14897: old priority 4, new priority 4
14899: old priority 4, new priority 4
15186: old priority 4, new priority 4
15190: old priority 4, new priority 4
15191: old priority 4, new priority 4
15531: old priority 4, new priority 4
15555: old priority 4, new priority 4
15584: old priority 4, new priority 4
15638: old priority 4, new priority 4
15655: old priority 4, new priority 4
15656: old priority 4, new priority 4
15657: old priority 4, new priority 4
15659: old priority 4, new priority 4
15660: old priority 4, new priority 4
15661: old priority 4, new priority 4
15662: old priority 4, new priority 4
15663: old priority 4, new priority 4
15664: old priority 4, new priority 4
15665: old priority 4, new priority 4
15666: old priority 4, new priority 4
15673: old priority 4, new priority 4
15687: old priority 4, new priority 4
 
Setting php to priority 6:
No processes for php running.
 
Setting MailScanner to priority 8:
No processes for MailScanner running.
 
Setting qmail-send to priority 10:
13943: old priority 0, new priority 10
 
Setting qmail-remote to priority 10:
No processes for qmail-remote running.
 
Setting clamav to priority 12:
No processes for clamav running.
 
Setting httpsd to priority 12:
4917: old priority 12, new priority 12
4922: old priority 12, new priority 12
6232: old priority 12, new priority 12
 
Setting freshclam to priority 12:
No processes for freshclam running.
 
Setting python2.2 to priority 12:
No processes for python2.2 running.
 
Setting clamd to priority 12:
13827: old priority 12, new priority 12
 
Setting mysqld to priority 12:
19665: old priority 12, new priority 12
19966: old priority 12, new priority 12
 
Setting spamd to priority 12:
4476: old priority 12, new priority 12
10190: old priority 12, new priority 12
27890: old priority 12, new priority 12
 
Setting spamassassin to priority 12:
No processes for spamassassin running.
 
Setting mysqld-max to priority 12:
No processes for mysqld-max running.

Nordbrest & Partner un nuevo proyecto

“Nada es tan estable como el cambio continuo”

Con esta frase de Heráclito damos vida a un nuevo proyecto, Nordbrest & Partner en el que intentaremos ayudar a empresas a optimizar sus procesos de negocio existentes así como a abrir nuevos mercados.

La empresa esta compuesta por Stephan Breuckmann y Daniel Bembibre Gude ambos venimos del mundo de las multinaciones TiC y tenemos una amplia experiencia en la apertura y manejo de grandes cuentas.

Un breve resumen de nuestra carta de presentación.
La preocupación de las empresas respecto a su negocio está cambiando de forma constante. Esto supone que tienen que hacer un esfuerzo de adaptación que les permita seguir siendo competitivas y mantener la rentabilidad. Los negocios deben compartir la información de forma rápida, no solamente dentro de su propia organización, sino también externamente con toda su cadena de proveedores y clientes.

NORDBREST & Partner [consultores] ayuda a sus clientes a enfrentarse a los retos de la tecnología y del negocio en continuo cambio.
Nuestra relación con los clientes es de colaboración; aportamos nuestra experiencia, mejores métodos y herramientas para desarrollar las estrategias y tecnologías de negocio que mejor se adapten a sus necesidades.

NORDBREST & Partner [consultores] le ofrece una amplia gama de servicios y soluciones dentro de éstas áreas:

  • Innovación Tecnológica
    technology & innovation
  • Desarrollo de Negocio
    business development

  • Contratación Externa
    outsourcing
  • Gestión Interina
    interim management

¿Por qué un consultor externo?

Hay muchas razones por qué la externalización es la vía más eficaz de afrontar nuevos retos:

Tiempo
La realidad en muchas empresas es, que el día a día nos come – pero ¿es aconsejable dejar los proyectos importantes para el futuro de su empresa para las horas extras o los fines de semana?

Experiencia
Sin duda, usted es especialista en su negocio – pero los retos de un nuevo proyecto son muy distintos de las exigencias de su propio negocio. No ponemos en duda que lo pueda hacer, pero ¿por qué perder tiempo en aprender lo que otros ya han experimentado?

Recursos
¿Existe la persona capaz de afrontar un proyecto nuevo y complejo en su empresa? ¿Y dispone del tiempo de hacerlo? ¿Piensa en emplear una persona nueva para esta tarea?

¡Es más económico!
NORDBREST & Partner [consultores] le ofrece los recursos que usted necesita para su proyecto. Tenemos un equipo de especialistas dedicado a solucionar su reto de una forma profesional y en el plazo de tiempo acordado. Por eso, usted sólo paga lo que realmente es necesario para realizar su proyecto. Ni más ni menos.

Nordbrest en la fería de emprendedores de Valencia

Monodevelop 2.8.1-2 src rpm para Mandriva 2011

Acabo de terminar de compilar este source rpm para mandriva 2011, con el anterior tuve problemas ya que la versión 2.8.1 estable se comía toda la memoria de la máquina durante la creación del “code completion db” para lo cual abri un bug en xamarin. Esto no quiere decir que monodevelop funcione mal, sino que el proyecto que estoy manejando ahora mismo tiene más de 35.000 archivos entre ficheros cs, aspx, y ascx.

Esto está solucionado en el código que he bajado desde el repo oficial, cuando cargas el proyecto por primera vez el consumo de memoria y cpu se mantiene estable.

El rpm se ha construido con los fuentes bajados desde el repo no de la versión estable.

git clone git://github.com/mono/monodevelop.git

Este es parte del spec del src, está basado en el spec de mandriva 2011 cooker

 

%define version 2.8
%define release %mkrel 2
%define gtksharp 1.9.5
%define monodoc 1.0
%define pkgconfigdir %_datadir/pkgconfig
 
Summary:	Full-featured IDE for mono and Gtk#
Name:		monodevelop
Version:	%{version}
Release:	%{release}
Source:		http://download.mono-project.com/sources/%name/%name-%version.tar.bz2
URL:		http://www.monodevelop.com/
License:	LGPLv2
Group:		Development/Other
#Requires:	gtksourceview-sharp &gt;= %gtksourceview
Requires:	gnome-sharp2 &gt;= %gtksharp
Requires:	glade-sharp2 &gt;= %gtksharp
Requires:	monodoc &gt;= %monodoc
Requires:	shared-mime-info
Requires:	xterm
Requires:	subversion
%if %mdvver &gt;= 201100
BuildRequires:	mono-addins-devel
%else
BuildRequires:	libmono-devel
BuildRequires:	mono-addins
%endif
BuildRequires:	gnome-desktop-sharp-devel
BuildRequires:	gnome-sharp2-devel &gt;= %gtksharp
BuildRequires:	glade-sharp2 &gt;= %gtksharp
BuildRequires:	monodoc &gt;= %monodoc
%if %mdvver &gt;= 201100
BuildRequires:	xsp-devel
%else
BuildRequires:	xsp
%endif
BuildRequires:	intltool
BuildArch:	noarch
BuildRoot:	%{_tmppath}/%{name}-%{version}-buildroot
Requires(post):		desktop-file-utils shared-mime-info
Requires(postun):	desktop-file-utils shared-mime-info
%define _requires_exceptions ^libg.*\\|lib64g.*\\|libp.*\\|lib64p.*\\|liba.*\\|lib64a.*
 
%description 
This is MonoDevelop which is intended to be a full-featured
integrated development environment (IDE) for mono and Gtk#.
It was originally a port of SharpDevelop 0.98.
 
%prep
%setup -q
 
%build
./configure --prefix=%_prefix --libdir=%_prefix/lib --enable-subversion --enable-monoextensions --disable-update-mimedb --disable-update-desktopdb 
 
make
 
%install

Para instalarlo solo tienes que hacer lo siguiente:

wget http://bmwfaq.com/danny-bembibre-gude/monodevelop-2.8-2.src.rpm
 
rpm -ivh monodevelop-2.8-2.src.rpm

El paquete se instalará en /home/usuario/rpmbuild revisa que tu entorno de creación de paquetes está completo

A continuación solo queda que recompiles el paquete, si falta alguna dependencia te avisará y tendrás que instalarla mediante urpmi

cd ~/rpmbuild
 
rpmbuild -ba SPECS/monodevelop.spec

Una vez concluido con éxito el proceso deberías probar que todo funciona bien antes de instalarlo, para eso vete a la carpeta build.
He incluido el script monodevelop para poder lanzar los exe

#!/bin/bash
 
#this script should be in $PREFIX/bin
MONO_EXEC="exec -a monodevelop mono"
EXE_PATH="MonoDevelop.exe"
 
_MD_REDIRECT_LOG="${MD_REDIRECT_LOG:-${XDG_CONFIG_HOME:-$HOME/.config}/MonoDevelop/log}"
 
_MONO_OPTIONS=$MONO_OPTIONS
cd ~/rpmbuild/BUILD/monodevelop-2.8/build/bin
 
#./monodevelop

Si todo te parece correcto puedes proceder a instalar el rpm el cual se encuentra en:

rpmbuild/RPMS/noarch/monodevelop-2.8-2-mdv2011.0.noarch.rpm

rpm -Uvh monodevelop-2.8-2-mdv2011.0.noarch.rpm

Ultimos cambios del spec:

%changelog
* Wed Oct 19 2011 Danny Bembibre Gude <bmwfaq@bmwfaq.com> 2.8-2mdv2011.0
- Codigo desde SVN git clone git://github.com/mono/monodevelop.git
- new version
- new source URL
 
* Mon Oct 10 2011 Götz Waschk <waschk@mandriva.org> 2.8-1mdv2012.0
+ Revision: 703990
- new version
- new source URL
 
* Wed Sep 07 2011 Götz Waschk <waschk@mandriva.org> 2.6-1
+ Revision: 698875
- new version
- new source URL
- drop patch 0
- update deps
- update configure flags
 
  + Sergey Zhemoitel <serg@mandriva.org>
    - add russian comment in .desktop
    - add russian comment in .desktop
    - add russian comment in .desktop
    - add russian comment in .desktop

Acceso al scr rpm monodevelop-2.8-2

Monodevelop despues de recompilar el paquete

Obteniendo más información de las excepciones StackTrace

Visual Studio 2010 viene con IntelliTrace, el cual te deja recolectar datos en profundidad de tu aplicación, desgraciadamente en Mono esto no existe. Actualmente estoy migrando a Mono una plataforma programada previamente en .NET 1.0/2.0/.3.5 con más de 35.000 archivos de código, muchos de ellos son ascx y aspx, por tanto me resulta más que interesante el poder obtener que archivos o controles asp están dando errores de sintaxis. La forma de obtener el archivo que tiene errores de sintaxis en mono es a través de la clase ParserException que contiene una propiedad FileName[iLocation] donde se indica que archivo falla en el parseo, que existe en System.web, desgraciadamente esta clase es internal.

También existe una clase ParseException dentro del ensamblado MonoDevelop.AspNet.dll este ensablado no es referenciable ya que no tiene un strongkey, tampoco sería viable cargarlo por reflection, ya que lo ideal sería referenciar el ensablado MonoDevelop.AspNet y hacer algo tan sencillo como lo siguiente con tu excepción ((Monodevelop.AspNet.Parser.Internal.ParseExcaption)ex).FileName.

Otro problema es que el port de sn.exe de mono no implementa la opción de eliminar la firma, lo cual permitiría firmarlo con otra clave

[dbembibre@linux Projects]$ sn -Vr MonoDevelop.AspNet.dll 
Mono StrongName - version 2.10.2.0
StrongName utility for signing assemblies
Copyright 2002, 2003 Motus Technologies. Copyright 2004-2008 Novell. BSD licensed.
 
Unimplemented option

Por suerte existe otra forma, con la clase StackTrace puedes obtener más información de tu excepcion de la siguiente manera.

catch (Exception ex)
{
 
#if DEBUG
 
System.Diagnostics.StackTrace mStack = new System.Diagnostics.StackTrace (ex, true);
 
System.Diagnostics.StackFrame[] mFrames = mStack.GetFrames ();
 
 foreach (System.Diagnostics.StackFrame stackFrame in mFrames)
 {
 
    Console.WriteLine ("Archivo con error: [{0}] Metodo : [{1}] Linea : [{2}] ", stackFrame.GetFileName (), stackFrame.GetMethod (),   stackFrame.GetFileLineNumber());
 
 }
#endif
 
}

Al final mirando el debugger he visto que MonoDevelop hace cast dinámico de las clases según el error, y que todos los errores relacionados con parsers de archivos ASP automáticamente encajan con clases de Excepción que implementan ILocation, por tanto nada más fácil que recoger el valor de la propiedad FileName via Reflection de esta forma

catch (Exception ex)
 
{
 
#if DEBUG
 
  object Archivo = ex.GetType ().GetProperty ("FileName").GetValue (ex, null);
 
#endif

Monodevelop 2.8-1 para Mandriva 2011

Si tu proyecto es muy grande, no te descargues el rpm, en mi caso el code completion database parsea cada archivo de código y está acabando con toda mi memoria libre

 

Os dejo por si alguno quiere usarlo el paquete de monodevelop 2.8-1 para mandriva 2011 (noarch), ya que mandriva viene por defecto con la versión 2.4.

Simplemente he descargado el src rpm de cooker y lo he compilado en mi maquina con un rpmbuild -bb.

El spec es este:

#define name monodevelop
%define version 2.8
%define release %mkrel 1
%define gtksharp 1.9.5
%define monodoc 1.0
%define pkgconfigdir %_datadir/pkgconfig
 
Summary:	Full-featured IDE for mono and Gtk#
Name:		monodevelop
Version:	%{version}
Release:	%{release}
Source:		http://download.mono-project.com/sources/%name/%name-%version.tar.bz2
Patch1:		%{name}.desktop.patch
URL:		http://www.monodevelop.com/
License:	LGPLv2
Group:		Development/Other
#Requires:	gtksourceview-sharp &gt;= %gtksourceview
Requires:	gnome-sharp2 &gt;= %gtksharp
Requires:	glade-sharp2 &gt;= %gtksharp
Requires:	monodoc &gt;= %monodoc
Requires:	shared-mime-info
Requires:	xterm
Requires:	subversion
%if %mdvver &gt;= 201100
BuildRequires:	mono-addins-devel
%else
BuildRequires:	libmono-devel
BuildRequires:	mono-addins
%endif
BuildRequires:	gnome-desktop-sharp-devel
BuildRequires:	gnome-sharp2-devel &gt;= %gtksharp
BuildRequires:	glade-sharp2 &gt;= %gtksharp
BuildRequires:	monodoc &gt;= %monodoc
%if %mdvver &gt;= 201100
BuildRequires:	xsp-devel
%else
BuildRequires:	xsp
%endif
BuildRequires:	intltool
BuildArch:	noarch
BuildRoot:	%{_tmppath}/%{name}-%{version}-buildroot
Requires(post):		desktop-file-utils shared-mime-info
Requires(postun):	desktop-file-utils shared-mime-info
%define _requires_exceptions ^libg.*\\|lib64g.*\\|libp.*\\|lib64p.*\\|liba.*\\|lib64a.*
 
%description
This is MonoDevelop which is intended to be a full-featured
integrated development environment (IDE) for mono and Gtk#.
It was originally a port of SharpDevelop 0.98.
 
%prep
%setup -q
 
%patch1 -p0
 
%build
./configure --prefix=%_prefix --libdir=%_prefix/lib --enable-subversion --enable-monoextensions --disable-update-mimedb --disable-update-desktopdb
#--enable-gtksourceview2
make
 
%install
rm -rf $RPM_BUILD_ROOT %name.lang
mkdir -p %{buildroot}/`monodoc --get-sourcesdir`
%makeinstall_std pkgconfigdir=%pkgconfigdir packagedir=%buildroot%_prefix/lib/monodevelop/AddIns/AspNetEdit MOZILLA_HOME=%buildroot%_prefix/lib/firefox-%mozver/
 
%find_lang %name
 
#gw replace bundled nunit by symlinks:
cd %buildroot%_prefix/lib/monodevelop/AddIns/NUnit
for x in nunit.*.dll; do
    ln -sf %_prefix/lib/mono/2.0/$x .
done
 
%if %mdkversion &lt; 200900
%post
%update_mime_database
%update_desktop_database
%update_menus
%update_icon_cache hicolor
%endif
 
%if %mdkversion &lt; 200900
%postun
%clean_mime_database
%clean_desktop_database
%clean_menus
%clean_icon_cache hicolor
%endif
 
%files -f %name.lang
%defattr(-,root,root)
%doc AUTHORS ChangeLog README
%{_bindir}/mdtool
%{_bindir}/monodevelop
%{_prefix}/lib/monodevelop/
%_mandir/man1/mdtool.1*
%_mandir/man1/monodevelop.1*
%{_datadir}/applications/monodevelop.desktop
%{_datadir}/mime/packages/monodevelop.xml
%_datadir/icons/hicolor/*/apps/monodevelop.*
%pkgconfigdir/monodevelop.pc
%pkgconfigdir/monodevelop-core-addins.pc
 
%clean
rm -rf $RPM_BUILD_ROOT

Descarga monodevelop-2.8-1

Leer nodos XML en Mono

No hay nada más fácil que leer nodos completos dentro de un XML con .NET/MONO, si bien existe XML parser para mi no hay nada más cómodo que el método selectsinglenode, de la clase XMLDocument, si le pones doble slash al principio busca el nodo que le indicas en todo el documento, y siempre a través de la propiead InnerText o InnerXML siempre puedes recoger el contenido del nodo. A continuación pongo un simple ejemplo de como recuperar un único valor de nodo.

El XML que uso:

El código para seleccionar un nodo XML:

Función que recibe las claves a buscar en el Documento:

protected const string REGISTRY_PATH = "/etc/XpressReloaded_Config.xml"; //Path al XML
 
		private static string MonoReadXML(string CompleteKey)
		{
			if(!File.Exists(REGISTRY_PATH))
				throw new System.IO.FileNotFoundException("MONO=&gt;FATAL=&gt;No existe un enlace simbolico en /etc/XpressReloaded_Config.xml");
 
			string sKeyName = string.Empty; string sValueName = string.Empty; string sRootKey=string.Empty; string sReturnValue = string.Empty;
 
			string[] _aNodes = CompleteKey.Split('\\');
 
			if(_aNodes.Length ==5)
			{
				sRootKey=_aNodes[1];
				sKeyName=_aNodes[3];
				sValueName=_aNodes[4];
			}
			else
			{
				return string.Empty;	
			}
 
			try 
			{
				XmlDocument _xmlDoc = new XmlDocument();
				_xmlDoc.Load(REGISTRY_PATH); //Cargar documento XML
				XmlNode _xmlList =  _xmlDoc.SelectSingleNode ("//" + sRootKey + "/SiteBuilder/" + sKeyName + "/" + sValueName); //Buscar el nodo por todo el documento
 
				if (_xmlList != null)
	               sReturnValue = _xmlList.InnerText; //Recuperar su valor interno
 
				_xmlList=null;
			}
			catch (Exception ex) {
			 	System.Diagnostics.Debug.WriteLine(ex.Message);
			}
 
			return sReturnValue;			
		}
	}

La llamada y salida de la función:

public static void Main (string[] args)
		{			
			Console.WriteLine(MonoReadXML("Software\\XPRESSWB80\\SiteBuilder\\DSN\\App"));
			Console.ReadLine();
		}

Libro sobre como trabajar con operadores de LinQ

Suelo visitar con más o menos frecuencia la biblioteca OpenLibra de los amigos de EtnasSoft, suelen recoger libros con licencia creative commons, y es una gran fuente de recursos en cuanto a libros técnicos; están ordenados por categorías, y podeis encontrar libros de algoritmia, cálculo, programación, administración de sistemas, etc. Todos con una calidad envidiable, y con una premisa clara, diseminar conocimientos sin afan de lucro.

El libro del que hablamos a continuación debería ser un recurso obligado de todos los que usamos con regularidad LinQ o manejamos bases de datos orientadas a objetos. El libro es de Jesús Rodríguez Rodríguez.

Os dejo un pequeña sinopsis del mismo:

LINQ define operadores de consulta estándar que permiten a lenguajes habilitados con LINQ filtrar, enumerar y crear proyecciones de varios tipos de colecciones usando la misma sintaxis. Tales colecciones pueden incluir vectores (arrays), clases enumerables, XML, conjuntos de datos desde bases de datos relacionales y orígenes de datos de terceros. El proyecto LINQ usa características de la versión 2.0 del .NET Framework, nuevos ensamblados relacionados con LINQ, y extensiones para los lenguajes C# y Visual Basic .NET. Microsoft ha distribuido una versión previa del LINQ, consistente de estas bibliotecas y compiladores para C# 3.0 y Visual Basic 9. Otros lenguajes, como F# y Nemerle, han anunciado brindar soporte preliminar.

El objetivo de crear LINQ es permitir que todo el código hecho en Visual Studio (incluidas las llamadas a bases de datos, datasets, XMLs) sean también orientados a objetos. Antes de LINQ, la manipulación de datos externos tenía un concepto más estructurado que orientado a objetos. Además LINQ trata de facilitar y estandarizar el acceso a dichos objetos.

Con esta obra podrás aprender a usar todos los operadores que nos ofrece este lenguaje incluyendo todas las sobrecargas de cada uno de ellos.

podeís descargarlo desde el siguiente enlace, operadores de LinQ

También os pueden interesar:

ASP.NET Guia de desarrollo de sitios y aplicaciones dinamicas

Guía de Arquitectura N-Capas DDD .NET 4.0

31 Days of refactoring

Llamadas pInvoke en Mono

En .NET pInvoke (System.Runtime.InteropServices) permite hacer llamadas a dll externas al framework, en Mono pInvoke existe casi desde el principio, y te permite llamar a cualquier librería del sistema, lo cual es muy util. Lo mejor es tratar de hacer todo con clases del framework pero muchas veces no lo tendrás disponible y necesitarás hacer una llamada externa, tal y como ocurría en los tiempos de Visual Basic donde se abusaba de estas llamadas a DLL de sistemas.

Aquí va un ejemplo simple que nos permite lanzar un top de sistema y ver como se actualizan los datos.

using System;
using System.Runtime.InteropServices;
 
namespace TestPInvoke
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            system ("top");
        }
 
        [DllImport ("libc")]
        static extern public void system (string command);
 
    }
}

El resultado de salida de nuestro código.

Y una un poco más divertida usando la aplicación figlet

using System;
using System.Runtime.InteropServices;
 
namespace TestPInvoke
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            system ("figlet Test de pInvoke");
        }
 
        [DllImport ("libc")]
        static extern public void system (string command);
 
    }
}