Ajustar resolución en Warcraft3
Abrir el registro de windows y editar las siguientes claves en:
HKEY_CURRENT_USER\Software\Blizzard Entertainment\Warcraft III\Video
resheight (defecto: 768) y reswidth (defecto: 1024)
via.
Consultas en SQL Server con IN
Al hacer una consulta de este estilo:
SELECT …. WHERE campo NOT IN (…)
No va a incluir las tuplas cuyo campo sea NULL. Por tanto si queremos incluirlos, habrá que indicarlo explícitamente:
SELECT …. WHERE campo NOT IN (…) OR campo IS NULL
¿Avanza el software tan rápido?
En el mundo de la computación y software parece que todo va muy muy rápido. Así que pensamos que la tecnología lleva un camino de avance cada vez más rápido y sin vuelta atrás. Sin en embargo leyendo el blog Eureka, me he planteado si realmente esto no es pura impresión y en realidad el software no es ajeno a la vida y sigue su ritmo.
Leyendo este blog y la trayectoria del transbordador espacial, parece que no todo va tan rápido y que para conseguir algo son necesarios varios decenios. En el mundo del software aunque parece que el ritmo de desarrollo es desenfrenado, si miramos a los sistemas y software de los 50–60-70 podemos comprobar que, tal vez, no hayamos avanzado tanto. Y las soluciones que se daban en muchos casos eran igual de válidas que las actuales.
Si un humano necesita 10 años para considerarse un experto en algo, como no van a ser necesarias muchas décadas para que cualquier tecnología termine siendo aceptada.
Tal vez este tipo de conceptos sean muy necesarios en el desarrollo de software para así construir sistemas que perduren por muchos años.
PS A pesar de no haber tenido nunca especial interés por la astronomía, el blog de Daniel Martín me parece uno de los mejores que leo y un descubrimiento reciente, y esto era simplemente una excusa para poder enlazarlo 😉
Simple cache para BusinessObjects
Debido a la naturaleza de mi trabajo, aplicaciones multitenant, y servicios M2M, para mejorar el rendimiento suelo cachear muchos objectos que tienen un tasa de lectura muy alta y de cambios muy muy pequeño. Así que para facilitar el trabajo, me he decido crear una pequeña utilidad.
/// <summary>
/// Concurrent cache for BusinessObject. It doesn´t clean cache, useful for small data.
/// </summary>
/// <typeparam name="T"></typeparam>
public class BusinessObjectCache<T>
where T : BusinessObject<T>
{
static ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
static volatile Dictionary<object, T> storage;
static BusinessObjectCache()
{
Locker.EnterWriteLock();
try
{
storage = new Dictionary<object, T>();
}
finally { Locker.ExitWriteLock(); }
}
public T Get(object id)
{
T o = null;
Locker.EnterReadLock();
try
{
if (storage.ContainsKey(id))
{
o = storage[id];
return o;
}
}
finally { Locker.ExitReadLock(); }
if (o == null)
{
Locker.EnterUpgradeableReadLock();
try
{
if (!storage.ContainsKey(id))
o = BusinessObject<T>.Retrieve(id);
if (o != null)
{
Locker.EnterWriteLock();
try
{
storage[id] = o;
}
finally { Locker.ExitWriteLock(); }
}
}
finally { Locker.ExitUpgradeableReadLock(); }
}
return o;
}
}
A ver si me lo curro y la hago LRU.
Simple HTTP GET en C#
La verdad es que, a veces, cosas sencillas se hacen complicadas en .NET y en mi opinión esta es una de ellas. Nada que objetar a que un framework tiene que ser lo menos restrictivo posible, pero en este caso no encuentro el sentido de que un error HTTP tenga que lanzar una excepción, yo personalmente la definiría como excepción vexing. Y bueno como estamos para ayudar pues con esta pequeña función todo será un poco más sencillo.
public static int Get(string uri, int timeout, out string response)
{
int statusCode = -1;
response = string.Empty;
HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
request.KeepAlive = false;
request.Timeout = timeout;
try
{
using (HttpWebResponse res = (HttpWebResponse)request.GetResponse() as HttpWebResponse)
{
statusCode = (int)res.StatusCode;
using (Stream dataStream = res.GetResponseStream())
{
using (StreamReader reader = new StreamReader(dataStream))
{
response = reader.ReadToEnd();
}
}
}
}
catch (WebException wex)
{
//http://msdn.microsoft.com/en-us/library/es54hw8e.aspx
if (wex.Status == WebExceptionStatus.ProtocolError)
{
// If status is WebExceptionStatus.ProtocolError,
// there has been a protocol error and a WebResponse
// should exist. Display the protocol error.
using (HttpWebResponse res = wex.Response as HttpWebResponse)
{
if (res != null)
{
statusCode = (int)res.StatusCode;
using (Stream s = wex.Response.GetResponseStream())
using (StreamReader reader = new StreamReader(s))
{
response = reader.ReadToEnd();
}
}
else
{ // no http status code available
throw wex;
}
}
}
else
{ // no http status code available
throw wex;
}
}
return statusCode;
}
Cuanto más veo ese código, menos me gusta como está diseñado.
Un par de enlaces.
DAOs sobre Dapper
La verdad es que los micro-ORMs están de moda (Massive, Dapper, PetaPOCO, SimpleData, etc). Basándome en esta abstracción y en mi querido Gentle.NET, me he decido a construir unos DAOs sobre Dapper, que es usado en Stackoverflow, y como características principales podemos decir: que es fuertemente tipado con una interfaz muy clara, y como extra soporta operaciones asíncronas a DB.
Creo que la mejor manera de entender el funcionamiento es con un ejemplo:
class Example
{
class Message
: BusinessObject<Message>
{
[PrimaryKey]
public Guid Id { get; set; }
public string DestinationAddress { get; set; }
public string SourceAddress { get; set; }
public string UserData { get; set; }
public int Ton { get; set; }
}
public void Example1()
{
Message m = new Message()
{
Id = Guid.NewGuid(),
DestinationAddress = "34612345678",
SourceAddress = "404",
UserData = "Example 01",
Ton = 1
};
m.Insert();
List<Message> l = Message.FindBy(new SqlCondition("DestinationAddress", Operator.Equals, "34612345678"));
m.Remove();
}
}
A continuación mostraremos el código de las funciones básicas de CRUD.
public class BusinessObject<T>
where T: class
{
public static SqlConnection GetConnection()
{
return ConnectionFactory.Create(typeof(T).Namespace);
}
public static T Retrieve(object id)
{
string sql = string.Empty;
DynamicParameters p = new DynamicParameters();
p.Add(GetPrimaryKey(), id, null, null, null);
StringBuilder sb = new StringBuilder()
.AppendFormat("select * from {0} where {1} = @{1}", GetTableName(), GetPrimaryKey());
return queryInternal(sb.ToString(), p).FirstOrDefault();
}
public void Insert()
{
string sql = string.Empty;
DynamicParameters p = new DynamicParameters();
StringBuilder columns = new StringBuilder(), values = new StringBuilder();
bool first = true;
foreach (string prop in GetProperties())
{
if (first)
{
columns.AppendFormat("{0}", prop);
values.AppendFormat("@{0}", prop);
}
else
{
columns.AppendFormat(", {0}", prop);
values.AppendFormat(", @{0}", prop);
}
p.Add(prop, getPropertyValue(this, prop), null, null, null);
first = false;
}
sql = string.Format("insert into {0} ({1}) values ({2})",
GetTableName(), columns.ToString(), values.ToString());
int res = executeInternal(sql, p);
}
public void Update()
{
// ...
}
public void Remove()
{
// ...
}
public static List<T> FindBy(SqlCondition[] conditions)
{
DynamicParameters p = new DynamicParameters();
StringBuilder sb = new StringBuilder()
.AppendFormat("select * from {0} where", typeof(T).Name);
bool first = true;
int i = 0;
foreach (SqlCondition c in conditions)
{
// for multiple conditions with same column
string var = c.PropertyName + (i++);
if (!first) sb.Append(" AND");
if (c.Value == null)
{
sb.AppendFormat(" {0} {1} NULL", c.PropertyName, OperatorHelper.ToString(c.Operator));
}
else
{
sb.AppendFormat(" {0} {1} @{2}", c.PropertyName, OperatorHelper.ToString(c.Operator), var);
p.Add(var, c.Value, null, null, null);
}
first = false;
}
return queryInternal(sb.ToString(), p);
}
protected static List<T> queryInternal(string sql, object param)
{
List<T> l = null;
using (var conn = GetConnection())
{
try
{
conn.Open();
l = conn.Query<T>(sql, param, null, false, 0, null).ToList();
}
finally { conn.Close(); }
}
return l;
}
Faltaría algo de código para representar las condiciones SQL, así como algunas funciones que usan reflección para optener el nombre de la tabla, propiedades o clave primaria.
La SIM, una ventaja de las operadoras
En el blog de cmt, se hacen eco de las intenciones de Apple para intentar liberarse de las operadoras. En mi opinión los operadores debería aprovechar esta ventaja e integrar más funcionalidad en ese chip, como por ejemplo, incluir RFID para posibilitar micro-pagos.
Deserializar en C# ignorando DTD
public static object Deserialize(System.Type type, string data)
{
XmlSerializer xmlSerializer = new XmlSerializer(type);
TextReader textReader = new StringReader(data);
XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = false;
settings.XmlResolver = null;
XmlReader xmlReader = XmlTextReader.Create(textReader, settings);
return xmlSerializer.Deserialize(xmlReader);
}
Agregar o quitar programas
Ir a agregar o quitar programas en windows: Win+R -> “appwiz.cpl” -> Enter
via.
#nolesvotes
A este pobre blog no lo visitan ni los robots de los buscadores, pero así y todo no quería dejar de enlazar.