<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>seiti.eti.br &#187; programação</title>
	<atom:link href="http://seiti.eti.br/blog/cat/programacao/feed" rel="self" type="application/rss+xml" />
	<link>http://seiti.eti.br/blog</link>
	<description>Programação e cacarecos tecnológicos</description>
	<lastBuildDate>Wed, 04 Aug 2010 23:44:01 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1-alpha</generator>
		<item>
		<title>KISS, YAGNI e DRY</title>
		<link>http://seiti.eti.br/blog/2010/kiss-yagni-e-dry</link>
		<comments>http://seiti.eti.br/blog/2010/kiss-yagni-e-dry#comments</comments>
		<pubDate>Wed, 04 Aug 2010 23:43:09 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=1208</guid>
		<description><![CDATA[Hoje fui lembrado de algo importante, que&#8230;, hmm.., bem&#8230;, às vezes é esquecido: o desenvolvedor deve entregar software. E acho que não sou só eu que devo ser lembrado disto, pois há até um site cujo propósito é lembrar isto &#8230; <a href="http://seiti.eti.br/blog/2010/kiss-yagni-e-dry">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Hoje fui lembrado de algo importante, que&#8230;, hmm.., bem&#8230;, às vezes é esquecido: o <strong>desenvolvedor</strong> deve <em>entregar software</em>.</p>
<p>E acho que não sou só eu que devo ser lembrado disto, pois há até um <a href="http://agilemanifesto.org/">site cujo propósito é lembrar isto</a> (bom,  existe <a href="http://sadtrombone.com/">site para tudo</a>, mas enfim&#8230;).</p>
<p>Como não poderia deixar de ser nesta área, existem alguns acrônimos e lemas que te auxiliam nesta tarefa tão importante, que é entregar um software de valor e respeito no prazo. <strong>KISS</strong>, <strong>YAGNI</strong> e <strong>DRY</strong>. Comecemos pelo mais simpático:</p>
<h2><em>KISS &#8211; Keep It Simple, Stupid</em></h2>
<p>Mantenha simples. A simplicidade facilita o entendimento. O que é simples é fácil de usar, de manipular. É fácil de explicar. Mas isto não quer dizer que a simplicidade como objetivo é algo simples. Complexo?</p>
<p>A simplicidade, a elegância são características que necessitam de experiência, de criatividade para serem alcançadas. Usando um  exemplo já surrado , o iPhone. Simples. Elegante. Lembra-se dos smartphones antes dele? Pois então. E o que fazer? Estudar, compreender, testar e inventar. E depois ver se sua mãe compreendeu seu invento.</p>
<h2><em>YAGNI &#8211; You Ain&#8217;t Gonna Need It</em></h2>
<p>Não implemente <em>nada</em>, a não ser que seja <em>necessário</em> para seu produto. Não produza o que não será usado. Senão será mais trabalho no momento de criar e no momento de dar manutenção.</p>
<p>Entra a questão: e o que realmente é necessário? Pergunta difícil. Se perguntar ao cliente o que é necessário, você terá de criar o <em>Facebook</em>.  A resposta requer experiência e análise fundamentada do problema em questão. Entra novamente um pouco de senso estético. <a href="http://www.brainyquote.com/quotes/quotes/e/edsgerdijk204339.html">Elegância</a>. Descreva as <em>features</em>. Elimine todas quanto possível.  Tire qualquer uma em que restem dúvidas.  Depois de criar este conjunto mínimo, escolha uma <em>feature</em> para jogar fora. Aí, talvez, sobre uma lista contendo apenas o que é necessário.</p>
<p>Mas sejamos pragmáticos também. A aplicação de YAGNI deve levar em conta também o custo de implementação. Se é barato fazer agora e barato depois, deixe para depois. Se é barato agora, mas ficará caríssimo depois, faça agora. Este conhecimento, de novo, requer prática e experiência.</p>
<h2><em>DRY &#8211; Don&#8217;t Repeat Yourself</em></h2>
<p>Uma regra, uma especificidade (repita em voz alta, comendo paçoca Amor), um pedaço do conhecimento deve estar declarada, escrita, de forma clara, em um único ponto do sistema.</p>
<p>Pode ser fácil. Ou bem difícil. Depende do tamanho. Do tamanho do produto e da equipe.  É muito comum equipes grandes de desenvolvimento escreverem diversas soluções para o mesmo problema, sem um ter conhecimento da solução do outro.</p>
<p>Já ouvi que isso ocorre em alguns lugares entre equipes de departamentos distintos, que são muito &#8220;ciosos&#8221; de seu código&#8230;</p>
<p>O fato é que é preciso que o sistema seja claro o suficiente e que os desenvolvedores se comuniquem de maneira eficiente para a aplicação do DRY. Como fazer isso? Seria uma boa perguntar ao Fred Brooks.</p>
<h2>Disk-sistema entregas rápidas</h2>
<p>E o que isto tudo significa? Significa a prática da <strong>Programação Zen</strong>. <em>O melhor código é o não-código</em>. Executar isso difícil. Requer perseverança e auto-controle. Exerçamos a <a href="http://seiti.eti.br/blog/?p=276">melhor qualidade de um programador</a>. Mantenha o sistema limpo, enxuto, conciso. Não crie, não produza a mais. Menos <em>features</em>, menos código, menos trabalho, menos tempo gasto. Talvez até dê para cumprir aquele prazo&#8230;.</p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2010/kiss-yagni-e-dry/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fluent NHibernate</title>
		<link>http://seiti.eti.br/blog/2010/fluent-nhibernate</link>
		<comments>http://seiti.eti.br/blog/2010/fluent-nhibernate#comments</comments>
		<pubDate>Tue, 20 Jul 2010 00:12:29 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[ddd]]></category>
		<category><![CDATA[net]]></category>
		<category><![CDATA[orm]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=1184</guid>
		<description><![CDATA[O NHibernate é um port para .NET do Hibernate, um mapeador objeto relacional (ou ORM) com esteróides. Vamos ver como usá-lo para mapear e persistir nossos objetos no banco de dados. O NHibernate é um grande auxílio para quem deseja &#8230; <a href="http://seiti.eti.br/blog/2010/fluent-nhibernate">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>O <a href="http://nhforge.org">NHibernate</a> é um port para .NET do <a href="http://hibernate.org/">Hibernate</a>, um <strong>mapeador objeto relacional</strong> (ou ORM) com esteróides. Vamos ver como usá-lo para mapear e persistir nossos objetos no banco de dados.</p>
<p>O NHibernate é um grande auxílio para quem deseja implementar um sistema usando DDD (não, não é quando você liga para o programador que mora longe. É <em>Domain Driven Design</em>).</p>
<div id="attachment_1185" class="wp-caption aligncenter" style="width: 74px"><a href="http://nhforge.org"><img class="size-full wp-image-1185 " title="NhLogo" src="http://seiti.eti.br/blog/wp-content/uploads/2010/07/NhLogo.png" alt="Me deixa dormir!" width="64" height="63" /></a><p class="wp-caption-text">Me deixa dormir!</p></div>
<p style="text-align: left;">Quem já usou o Hibernate sabe que configurá-lo pode ser a porta de entrada para o primeiro dos <a href="http://en.wikipedia.org/wiki/Inferno_%28Dante%29">nove círculos do inferno</a>. Bom, não passei por isto,  pois nunca havia usado diretamente o Hibernate. Se existe algo  bom em chegar na festa por <strong>último</strong> no mundo do desenvolvimento, é de ter mais coisas prontas e mastigadinhas. Entra então o <strong><em>Fluent NHibernate</em></strong>.</p>
<h2 style="text-align: left;">Historinha para bovinos hibernarem</h2>
<p style="text-align: left;">Primeiro o contexto. Enfrento um código legado (código legado == código sem testes, segundo <a href="http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052">Feathers</a>) que usa o framework <em>Castle ActiveRecord</em> (Castle AR). Embora este framework facilite bastante a vida, poupando o pobre programador da tarefa de escrever muito código CRUD, ganhando uma tendinite, ele não se dá muito bem com o DDD, tornando mais trabalhoso que o necessário a separação das <em>Entidades</em> do sistema de <em>persistência.</em></p>
<p style="text-align: left;">Outro problema é que, apesar do Castle AR fornecer uma camada de abstração sobre o Hibernate, é necessário que você saiba como o Hibernate funciona. Decidi então me livrar do Castle AR e usar apenas o  Hibernate. E como não quero editar os arquivos XML do Hibernate eu mesmo (o Castle AR fazia este trabalho) decidi usar o Fluent NHibernate.</p>
<h2>Programação, sistemas e zumbis</h2>
<p>O Fluent NHibernate segue uma sintaxe <em>fluente</em> para realizar toda a configuração do Hibernate usando a própria linguagem de programação. No meu caso, C#.</p>
<p>Primeiro um esquema altamente complexo do sistema que servirá de exemplo:</p>
<div class="wp-caption aligncenter" style="width: 510px"><a title="Diagrama do sistema by Seiti Yamashiro, on Flickr" href="http://www.flickr.com/photos/seiti/4809510719/"><img src="http://farm5.static.flickr.com/4114/4809510719_ef4e9bea45.jpg" alt="Diagrama do sistema" width="500" height="281" /></a><p class="wp-caption-text">Chamem o Chris Redfield!</p></div>
<p style="text-align: left;">Um <span style="text-decoration: line-through;">RaccoonCity</span> <em>City</em> possui inúmeros <em>Zombies</em>. O <em>City</em> tem uma data, <em>Month</em>, com mês e ano, de quando se iniciou a infecção de sua população. <em>Zombie</em> possui uma data, <em>Month</em>,  de quando ele mesmo foi infectado. Por enquanto não podemos estimar estas datas com precisão de dias, por isso queremos apenas mês e ano.</p>
<p>O diagrama acima gerou as seguintes classes:<br />
<a href="http://seiti.eti.br/blog/wp-content/uploads/2010/07/screen1.png"><img class="aligncenter size-full wp-image-1187" title="screen" src="http://seiti.eti.br/blog/wp-content/uploads/2010/07/screen1.png" alt="" width="462" height="294" /></a></p>
<ul>
<li><tt>City</tt> é uma <em>Entidade</em>. E é uma Raíz de  Agregado, ou <em>Aggregate Root</em>;</li>
<li><tt>Zombie</tt> é um <em>Objeto Valor</em>, ou<em> Value Object</em>. Quer dizer que todos os zumbis são iguais, desde que tenham as mesmas propriedades: <em>FormerName</em> e <em>Infected</em>. Deixei um Id mesmo assim;</li>
<li><tt>Month</tt> também é um Objeto Valor. Ele determina um mês e ano. Não estou interessado no dia.</li>
</ul>
<p>Uma preocupação na modelagem foi quanto à lista <em>Zombies</em>. Para se adicionar um Zombie em um City é preciso usar o método AddZombie(). Assim tenho um lugar onde posso checar e validar o Zombie antes da adição.</p>
<p>Mas se eu exponho Zombies como um <em>List&lt;Zombie&gt;</em> nada impede o programador de fazer isso:</p>
<pre class="brush: csharp;">
City raccoon = new City(&quot;Raccoon City&quot;, new Month(2010, 4));
raccoon.Zombies.Add(new Zombie(&quot;Zé Ninguém&quot;, new Month(2010, 7)));
</pre>
<p>ao invés de:</p>
<pre class="brush: csharp;">
City raccoon = new City(&quot;Raccoon City&quot;, new Month(2010, 4));
raccoon.AddZombie(new Zombie(&quot;Zé Ninguém&quot;, new Month(2010, 7)));
</pre>
<p>Para resolver este problema eu guardo a lista como um <em>List&lt;Zombie&gt;</em> e exponho apenas um <em>IEnumerable&lt;Zombie&gt;:</em></p>
<pre class="brush: csharp;">
    public class City
    {
        public virtual int Id { get; private set; }

        public virtual string Name { get; private set; }

        public virtual Month InfectionStart { get; private set; }

        private readonly IList&lt;Zombie&gt; _zombies = new List&lt;Zombie&gt;();

        public virtual IEnumerable&lt;Zombie&gt; Zombies
        {
            get { return _zombies; }
        }

        protected City()
        {}

        public City(string name, Month startMonth)
        {
            Name = name;
            InfectionStart = startMonth;
        }

        public virtual void AddZombie(Zombie z)
        {
            _zombies.Add(z);
        }

    }
</pre>
<p>O IEnumerable apenas expõe método de consulta. Exatamente o que eu queria.</p>
<p>Vamos agora implementar a classe <em>Zombie</em>. Esta acaba sendo mais complicada, pois se trata de um VO (<em>Value Object</em>). É necessário realizar um override nos métodos <em>Equals()</em> e <em>GetHashCode()</em> para que o sistema possa comprar dois zumbis com as mesmas propriedades, mesmo que de instâncias diferentes, e devolver um resultado útil. E já podemos aproveitar para fazer override nos operadores == e !=, para que devolvam o mesmo resultado que o Equals():</p>
<pre class="brush: csharp;">
    public class Zombie
    {
        public virtual int Id { get; private set;}
        public virtual string FormerName { get; set; }
        public virtual Month Infected { get; set; }

        public static bool operator ==(Zombie b1, Zombie b2)
        {
            return b1.FormerName == b2.FormerName &amp;&amp; b1.Infected == b2.Infected;
        }

        public static bool operator !=(Zombie b1, Zombie b2)
        {
            return b1.FormerName != b2.FormerName || b1.Infected != b2.Infected;
        }

        public static bool operator &gt;(Zombie b1, Zombie b2)
        {
            return b1.Infected &gt; b2.Infected;
        }

        public static bool operator &lt;(Zombie b1, Zombie b2)
        {
            return b1.Infected &lt; b2.Infected;
        }

        public static bool operator &gt;=(Zombie b1, Zombie b2)
        {
            return b1.Infected &gt;= b2.Infected;
        }

        public static bool operator &lt;=(Zombie b1, Zombie b2)
        {
            return b1.Infected &lt;= b2.Infected;
        }

        public override bool Equals(object obj)
        {
            if (!(obj is Zombie))
                return false;

            return this == (Zombie)obj;
        }

        public override int GetHashCode()
        {
            return FormerName.GetHashCode() ^ Infected.GetHashCode();
        }
    }
</pre>
<p>Até aproveitei para implementar os operadores &lt; e &gt;, que dependem da data de infecção do safado.</p>
<p>E só resta a classe <em>Month</em>:</p>
<pre class="brush: csharp;">
    public class Month: IComparable
    {
        private int Dia { get { return 1; } }
        public int Mes { get; private set; }
        public int Ano { get; private set; }

        protected Month()
        {}

        public Month(int ano, int mes)
        {
            if (!AnoValido(ano))
                throw new ArgumentOutOfRangeException(String.Format(&quot;Ano não cabível. Ano apresentado: {0}&quot;, ano));

             if (!MesValido(mes))
                throw new ArgumentOutOfRangeException(String.Format(&quot;Mês não cabível. Mês apresentado: {0}&quot;, mes));

            Ano = ano;
            Mes = mes;
        }

        private bool AnoValido(int ano)
        {
            // Valores válidos para o SQL Server.
            // Observe que dado o escopo do problema não faz sentido nada fora deste intevalo mesmo.
            if (1753 &lt;= ano &amp;&amp; ano &lt;= 9999)
                return true;

            return false;
        }

        private bool MesValido(int mes)
        {
            if (1 &lt;= mes &amp;&amp; mes &lt;= 12)
                return true;

            return false;
        }

        public DateTime AsDateTime()
        {
            return new DateTime(Ano, Mes, Dia);
        }

        public override string ToString()
        {
            return AsDateTime().ToString();
        }

        public static bool operator ==(Month d1, Month d2)
        {
            return d1.Ano == d2.Ano &amp;&amp; d1.Mes == d2.Mes;
        }

        public static bool operator !=(Month d1, Month d2)
        {
            return d1.Ano != d2.Ano || d1.Mes != d2.Mes;
        }

        public static bool operator &lt;=(Month d1, Month d2)
        {
            if (d1 == d2)
                return true;

            if (d1.Ano &lt; d2.Ano)
                return true;

            if (d1.Ano &gt; d2.Ano)
                return false;

            if (d1.Mes &lt; d2.Mes)
                return true;

            return false;
        }

        public static bool operator &gt;=(Month d1, Month d2)
        {
            if (d1 == d2)
                return true;

            if (d1.Ano &gt; d2.Ano)
                return true;

            if (d1.Ano &lt; d2.Ano)
                return false;

            if (d1.Mes &gt; d2.Mes)
                return true;

            return false;
        }

        public static bool operator &lt;(Month d1, Month d2)
        {
            if (d1 == d2)
                return false;

            if (d1.Ano &lt; d2.Ano)
                return true;

            if (d1.Ano &gt; d2.Ano)
                return false;

            if (d1.Mes &lt; d2.Mes)
                return true;

            return false;
        }

        public static bool operator &gt;(Month d1, Month d2)
        {
            if (d1 == d2)
                return false;

            if (d1.Ano &gt; d2.Ano)
                return true;

            if (d1.Ano &lt; d2.Ano)
                return false;

            if (d1.Mes &gt; d2.Mes)
                return true;

            return false;
        }

        public override bool Equals(object obj)
        {
            if (!(obj is Month))
                return false;

            return this == (Month) obj;
        }

        public override int GetHashCode()
        {
            return Ano.GetHashCode() ^ Mes.GetHashCode();
        }

        public int CompareTo(object obj)
        {
            Month d = (Month)obj;

            if (this &lt; d)
                return -1;
            else if (this &gt; d)
                return 1;

            return 0;

        }
    }
</pre>
<p>Mesma história dos Zumbis: implementei Equals(), e GetHashCode() e os operadores. Asism posso escrever código do tipo:</p>
<pre class="brush: csharp;">
Data d1 = new Data(2000, 1);
Data d2 = new Data(2000, 1);
if (d1 == d2)
    doSomething();
else if (d1 &gt; d2)
    doSomethingElse();
else if (d1 &lt; d2)
    doEtc();
</pre>
<p>Com as classes do modelo implementadas, posso adicionar validações, testes e tudo mais, sem me preocupar com a camada de persistência, tornando a criação de testes unitários um trabalho bem simples. Mas este post não é sobre DDD.</p>
<h2>Persistência != Teimosia</h2>
<p>Vamos mapear nossas estimadas classes, usando o <em>Fluent NHibernate</em>, para que possam ir para o banco de dados.  Comecemos com a classe <em>Zombie</em>, mapeada pela classe <strong>ZombieMap</strong>:</p>
<pre class="brush: csharp;">
public class ZombieMap: ClassMap&lt;Zombie&gt;
{
    public ZombieMap()
    {
        Id(x =&gt; x.Id);
        Map(x =&gt; x.FormerName);
        Map(x =&gt; x.Infected);
    }
}
</pre>
<p>Bem simples, não? Isto nos informa que a classe <em>Zombie</em> será mapeada para uma tabela <tt>Zombie</tt>, com campos <strong>FormerName</strong> (com tipo  nvarchar(255))  e <strong>Infected</strong> (com tipo &#8230; hmmm, calma aí, veremos adiante).</p>
<p>Vamos ver a classe City:</p>
<pre class="brush: csharp;">
public class CityMap: ClassMap&lt;City&gt;
{
    public  CityMap()
    {
        Id(x =&gt; x.Id);
        Map(x =&gt; x.Name);
        Map(x =&gt; x.InfectionStart);
        HasMany&lt;Zombie&gt;(x =&gt; x.Zombies)
            .Access.CamelCaseField(Prefix.Underscore)
            .Cascade.AllDeleteOrphan()
            .AsBag();
    }
}
</pre>
<p>Também bem simples. A diferença aqui fica por conta do <strong>HasMany&lt;Zombie&gt;</strong>, cujo significado é bem simples, um City possui muitos Zombies.</p>
<p>Algo não tão óbvio é o <em>Access.CamelCaseField(Prefix.Underscore)</em>. Isto diz que a propriedade Zombies possui um campo que serve de suporte, com nome escrito no estilo camelCase (diferente de PascalCase) e iniciado por um underscore. Se trata do campo <strong>_zombies</strong>, que é Zombies escrito em camelCase e iniciado por underscore.</p>
<p><em>Cascade.AllDeleteOrphans()</em> informa ao NHibernate para apagar os Zombies órfãos, quer dizer, que não possuem um City.</p>
<p><em>AsBag()</em> é mais complicado. Primeiro é preciso entender que o NHibernate lida com <a href="http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/06/12/mapping-collections-in-nhibernate-part-1.aspx">vários tipos de coleções</a>: <strong>Set</strong>, <strong>Bag</strong>, <strong>Map</strong> e <strong>List</strong>. Cada uma com características próprias. No caso optei por <strong>bag</strong>, mas poderia ter usado <strong>list</strong> (que é um bag indexado).</p>
<p>Bom, resta agora a classe <em><strong>Month</strong></em>. Decidi não guardar o month em uma tabela própria. Ela nada mais é que uma data, onde apenas mês e ano importam. Então é apropriado guardá-lo em um campo DATETIME no banco de dados.</p>
<p>Para isso acontecer configuramos o NHibernate para tratar o Month como um DATETIME na hora de persistir tanto o <em>City</em> quanto o <em>Zombie</em> (campos <em>Infected</em>), criando uma classe que implementa a interface <strong><em>IUserType</em></strong>:</p>
<pre class="brush: csharp;">
public class MonthUserType: IUserType
{
    public new bool Equals(object x, object y)
    {
        if (ReferenceEquals(x, y)) return true;

        if (x == null || y == null) return false;

        return x.Equals(y);
    }

    public int GetHashCode(object x)
    {
        return x == null ? typeof(Month).GetHashCode() : x.GetHashCode();
    }

    //voltando do BD: passar de datetime para Month
    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        var date = NHibernateUtil.DateTime.NullSafeGet(rs, names[0]) as DateTime?;

        if (date == null) return null;

        return new Month(date.Value.Year, date.Value.Month);
    }

    //indo pro BD: passar de Month para datetime
    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        DateTime? date = null;

        if (value != null)
            date = ((Month) value).AsDateTime();

        NHibernateUtil.DateTime.NullSafeSet(cmd, date, index);
    }

    public object DeepCopy(object value)
    {
        return value;
    }

    public object Replace(object original, object target, object owner)
    {
        return original;
    }

    public object Assemble(object cached, object owner)
    {
        return cached;
    }

    public object Disassemble(object value)
    {
        return value;
    }

    public SqlType[] SqlTypes
    {
        get { return new[] { NHibernateUtil.DateTime.SqlType }; }
    }

    public Type ReturnedType
    {
        get { return typeof (Month); }
    }

    public bool IsMutable
    {
        get { return false; }
    }
}
</pre>
<p>Esta classe vai tratar do trabalho de converter de Month para DATETIME e vice-versa. Para usar nosso MonthUserType é necessário configurar os mapeamentos das classes City e Zombie:</p>
<pre class="brush: csharp;">
Map(x =&gt; x.Infected).CustomType(typeof(MonthUserType));
</pre>
<p>Mas eu não usei esta abordagem. Imagine que tenhamos mais que essas duas classes para alterar ou que eu deseje deixar a configuração mais limpa.  Podemos deixar os mapeamentos já configurados do mesmo jeito, e informar o NHibernate  a usar o MonthUserType usando <a href="http://wiki.fluentnhibernate.org/Conventions">Convenções</a> (<em>Conventions</em>).</p>
<p>Basta implementar uma classe com a informação de que nossa convenção é usar MonthUserType para persistir objetos Month:</p>
<pre class="brush: csharp;">
    public class MonthUserTypeConvention: UserTypeConvention&lt;MonthUserType&gt;
    {
    }
</pre>
<p>É assim mesmo, vazio. No caso nem foi necessário realizar nenhum override dos métodos <em>Apply()</em> ou <em>Accept()</em>.</p>
<p>E pronto! Suas classes estão prontas para serem persistidas no banco de dados.</p>
<h2>Infraestrutura</h2>
<p>Bom, mas para se gravar os dados no banco é preciso ao menos saber como se conectar ao banco. Vamos facilitar nossa vida criando um método fábrica de objetos fábricas (ou algo assim):</p>
<pre class="brush: csharp;">
    public static class FluentSessionFactory
    {
        public static ISessionFactory CreateFactory(string connectionString)
        {
            return Fluently.Configure()
              .Database(MsSqlConfiguration.MsSql2005.ConnectionString(connectionString))
              .Mappings(
                m =&gt; m.FluentMappings
                    .AddFromAssemblyOf&lt;City&gt;()
                    .Conventions.AddFromAssemblyOf&lt;MonthUserTypeConvention&gt;()
              )
              .ExposeConfiguration(BuildSchema)
              .BuildSessionFactory();
        }

        private static void BuildSchema(Configuration config)
        {
            SchemaExport schema = new SchemaExport(config);
            schema.Drop(false, true);
            schema.Create(false, true);
        }

    }
</pre>
<p>Note que meu banco é um Sql Server 2005. Acerte o código para teu banco de dados. E para usar:</p>
<pre class="brush: csharp;">
ISessionFactory factory = FluentSessionFactory.CreateFactory(@&quot;Database=test_db;Server=localhost\sqlexpress;user=theuser;pwd=thepassword;&quot;);
ISession session = factory.OpenSession();
/** cria objetos e manda para o bd usando Session.Save(objeto) **/
session.Close();
</pre>
<p>Mas tome <strong>cuidado</strong>. Note um <em>schema.Drop()</em> e um <em>schema.Create()</em> lá em cima. Eles jogam as tabelas do banco fora e depois recriam-nas. Bom para o ambiente de desenvolvimento. Ruim para ambiente de produção. Muito ruim.</p>
<h2>1, 2, 3 Testando</h2>
<p>Nada melhor que usar testes automatizados para verificar se está tudo funcionando. Quer dizer, comer camarão na praia tomando cerveja é melhor que isso, mas vamos lá.</p>
<p>O Fluent NHibernate conta com um método muito útil para verificar se os mapeamentos estão redondinhos. Se trata do <em>PersistenceSpecification.VerifyTheMappings().</em></p>
<p>Veja como é simples:<em><br />
</em></p>
<pre class="brush: csharp;">
[TestClass]
public class CityMapTest
{
    private static readonly string ConnString = @&quot;Database=db_test;Server=localhost\sqlexpress;user=theuser;pwd=thepassword;&quot;;
    private static ISession Session;

    private TestContext testContextInstance;

    public TestContext TestContext
    {
        get
        {
            return testContextInstance;
        }
        set
        {
            testContextInstance = value;
        }
    }

    [ClassInitialize()]
    public static void MyClassInitialize(TestContext testContext)
    {
        ISessionFactory factory = FluentSessionFactory.CreateFactory(ConnString);
        Session = factory.OpenSession();
    }

    [ClassCleanup()]
    public static void MyClassCleanup()
    {
        Session.Close();
    }

    [TestMethod]
    public void CrudTest()
    {
        new PersistenceSpecification&lt;City&gt;(Session)
            .CheckProperty(x =&gt; x.Id, 1)
            .CheckProperty(x =&gt; x.Name, &quot;Raccoon City&quot;)
            .CheckProperty(x =&gt; x.InfectionStart, new Month(1998, 8))
            .CheckList(
                x =&gt; x.Zombies,
                new []
                {
                    new Zombie { FormerName  =  &quot;John Doe&quot;, Infected = new Month(1998, 7) },
                    new Zombie { FormerName  =  &quot;José da Silva&quot;, Infected = new Month(1998, 6) }
                },
                (r, z) =&gt; r.AddZombie(z))
            .VerifyTheMappings();
    }
}
</pre>
<p>Ao executar o teste acima serão criadas as tabelas City e Zombie no banco de dados, que serão preenchidas com os dados fornecidos. Depois esses dados serão lidos e convetidos em objetos do sistema. Daí estes objetos serão comparados com os objetos originais. Se estiver tudo ok, o teste sinalizará <strong>verde</strong>. Se não, hora de corrigir <strong>bugs</strong>.</p>
<p>E é isso. Ah, para quem quiser o <a href="http://dl.dropbox.com/u/2295190/blog/FluentNH.zip">código do projeto&#8230;</a>
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2009/linq-to-sql" rel="bookmark" title="13 de abril de 2009">Linq to Sql</a></li>
<li><a href="http://seiti.eti.br/blog/2008/ddd" rel="bookmark" title="28 de maio de 2008">DDD</a></li>
<li><a href="http://seiti.eti.br/blog/2009/encodings-e-charsets-em-aspnet" rel="bookmark" title="13 de maio de 2009">Encodings e charsets em Asp.NET</a></li>
<li><a href="http://seiti.eti.br/blog/2009/dns-poisoning-na-net-virtua" rel="bookmark" title="14 de abril de 2009">DNS poisoning na NET Virtua</a></li>
</ul>
<p><!-- Similar Posts took 7.967 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2010/fluent-nhibernate/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Exceções do .Net</title>
		<link>http://seiti.eti.br/blog/2010/excecoes-do-net</link>
		<comments>http://seiti.eti.br/blog/2010/excecoes-do-net#comments</comments>
		<pubDate>Wed, 07 Jul 2010 21:22:48 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=1176</guid>
		<description><![CDATA[Uma lista de exceções úteis para utilizar em seu sistema, sem ter que criar sempre outra classe e escrever mais código. Ultimamente tenho pensado numa programação Zen: o melhor código é o não-código. Quanto menos código você escrever, menos terá &#8230; <a href="http://seiti.eti.br/blog/2010/excecoes-do-net">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Uma lista de exceções úteis para utilizar em seu sistema, sem ter que criar sempre outra classe e escrever mais código.</p>
<p>Ultimamente tenho pensado numa programação Zen: o melhor código é o não-código. Quanto menos código você escrever, menos terá para manter, menos terá para entender, menos terá para depurar. Ou talvez esteja exacerbando apenas a <a href="http://seiti.eti.br/blog/?p=276">melhor qualidade de um programador</a>.</p>
<p>Chega de papo-furado, segue a lista (todas no namespace <tt>System</tt>):</p>
<table>
<tr>
<td>
ApplicationException
</td>
<td>
The exception that is thrown when a non-fatal application error occurs.
</td>
</tr>
<tr>
<td>
ArgumentException
</td>
<td>
The exception that is thrown when one of the arguments provided to a method is not valid.
</td>
</tr>
<tr>
<td>
<p>ArgumentNullException
</td>
<td>
<p>The exception that is thrown when a null reference (Nothing in Visual Basic) is passed to a method that does not accept it as a valid argument.
</td>
</tr>
<tr>
<td>
<p>ArgumentOutOfRangeException
</td>
<td>
<p>The exception that is thrown when the value of an argument is outside the allowable range of values as defined by the invoked method.
</td>
</tr>
<tr>
<td>
ArithmeticException
</td>
<td>
<p>The exception that is thrown for errors in an arithmetic, casting, or conversion operation.
</td>
</tr>
<tr>
<td>
<p>ArrayTypeMismatchException
</td>
<td>
<p>The exception that is thrown when an attempt is made to store an element of the wrong type within an array.
</td>
</tr>
<tr>
<td>
FieldAccessException
</td>
<td>
<p>The exception that is thrown when there is an invalid attempt to access a private or protected field inside a class.</p>
</td>
</tr>
<tr>
<td>
FormatException
</td>
<td>
<p>The exception that is thrown when the format of an argument does not meet the parameter specifications of the invoked method.
</td>
</tr>
<tr>
<td>
IndexOutOfRangeException
</td>
<td>
<p>The exception that is thrown when an attempt is made to access an element of an array with an index that is outside the bounds of the array. This class cannot be inherited.
</td>
</tr>
<tr>
<td>
<p>InvalidOperationException
</td>
<td>
<p>The exception that is thrown when a method call is invalid for the object’s current state.
</td>
</tr>
<tr>
<td>
NotFiniteNumberException
</td>
<td>
<p>The exception that is thrown when a floating-point value is positive infinity, negative infinity, or Not-a-Number (NaN).
</td>
</tr>
<tr>
<td>
NotImplementedException
</td>
<td>
<p>The exception that is thrown when a requested method or operation is not implemented.</p>
</td>
</tr>
<tr>
<td>
NotSupportedException
</td>
<td>
<p>The exception that is thrown when an invoked method is not supported, or when there is an attempt to read, seek, or write to a stream that does not support the invoked functionality.</p>
</td>
</tr>
<tr>
<td>
NullReferenceException
</td>
<td>
<p>The exception that is thrown when there is an attempt to dereference a null object reference.</p>
</td>
</tr>
<tr>
<td>
ObjectDisposedException
</td>
<td>
<p>The exception that is thrown when an operation is performed on a disposed object.
</td>
</tr>
<tr>
<td>
<p>PlatformNotSupportedException
</td>
<td>
<p>The exception that is thrown when a feature does not run on a particular platform.
</td>
</tr>
<tr>
<td>
<p>RankException
</td>
<td>
<p>The exception that is thrown when an array with the wrong number of dimensions is passed to a method.</p>
</td>
</tr>
<tr>
<td>
<p>SystemException
</td>
<td>
<p>Defines the base class for predefined exceptions in the namespace.
</td>
</tr>
<tr>
<td>
<p>TimeoutException
</td>
<td>
<p>The exception that is thrown when the time allotted for a process or operation has expired.
</td>
</tr>
<tr>
<td>
<p>TypeInitializationException
</td>
<td>
<p>The exception that is thrown as a wrapper around the exception thrown by the class initializer. This class cannot be inherited.</p>
</td>
</tr>
<tr>
<td>
<p>UnauthorizedAccessException
</td>
<td>
<p>The exception that is thrown when the operating system denies access because of an I/O error or a specific type of security error.</p>
</td>
</tr>
</table>
<p>Fonte: <a href="http://mikevallotton.wordpress.com/2009/07/08/net-exceptions-all-of-them/">http://mikevallotton.wordpress.com/2009/07/08/net-exceptions-all-of-them/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2010/excecoes-do-net/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Erro no deploy automático: Hudson versus MSBuild</title>
		<link>http://seiti.eti.br/blog/2010/erro-no-deploy-automatico-hudson-versus-msbuild</link>
		<comments>http://seiti.eti.br/blog/2010/erro-no-deploy-automatico-hudson-versus-msbuild#comments</comments>
		<pubDate>Tue, 11 May 2010 23:48:15 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[desenvolvimento]]></category>
		<category><![CDATA[msbuild]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=1126</guid>
		<description><![CDATA[Usamos o excelente Hudson como servidor de integração contínua, junto do plugin MSBuild. Mas estes dias criei um projeto no Hudson, referente à uma solução já no framework .NET v4, escrita no Visual Studio 2010 (v10). O primeiro passo foi &#8230; <a href="http://seiti.eti.br/blog/2010/erro-no-deploy-automatico-hudson-versus-msbuild">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Usamos o excelente Hudson como servidor de integração contínua, junto do plugin MSBuild.</p>
<div class="wp-caption aligncenter" style="width: 106px"><a href="http://hudson-ci.org/"><img title="Hudson" src="http://hudson-ci.org/images/butler.png" alt="" width="96" height="96" /></a><p class="wp-caption-text">O fiel mordomo</p></div>
<p>Mas estes dias criei um projeto no Hudson, referente à uma solução já no framework .NET v4, escrita no Visual Studio 2010 (v10).</p>
<p>O primeiro passo foi entrar nas configurações do Hudson e criar outra entrada para o plugin MSBuild, apontando para a versão 4 do mesmo. Basta ir para <em>Gerenciar Hudson</em> → <em>Configurar Sistema</em> → <em>MSBuild</em> e incluir:</p>
<blockquote>
<pre>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</pre>
</blockquote>
<p>Feito isto, configurei o novo projeto para usar esta nova entrada do MSBuild. E o projeto falhou na construção com a seguinte mensagem:</p>
<blockquote>
<pre style="overflow: auto;">error MSB4019: The imported project "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" was not found. Confirm that the path in the &lt;Import&gt; declaration is correct, and that the file exists on disk.
</pre>
</blockquote>
<p>O jeito foi atender a demanda: criei as respectivas pastas e copiei o arquivo do meu micro para o servidor. Pronto. Agora só resta resolver alguns pepinos com <em>assemblies</em>&#8230;</p>
<p><strong>Update</strong>: parece que preciso instalar ou o Visual Studio 2010 ou o Windows 7 SDK  no servidor em questão. Mas ocorrem dois problemas: (1) o VS2010 é caro e (2) o SDK ainda <a href="http://blogs.msdn.com/windowssdk/archive/2010/04/07/coming-soon-win-sdk-for-windows-7-and-net-4.aspx">não saiu</a>. O jeito é aguardar meados de junho.
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2009/compilando-seu-web-application-project-com-o-msbuild" rel="bookmark" title="6 de maio de 2009">Compilando seu Web Application Project com o MSBuild</a></li>
<li><a href="http://seiti.eti.br/blog/2009/problema-rodando-testes-mbunit-no-vs2008-test-runner" rel="bookmark" title="3 de agosto de 2009">Problema rodando testes MbUnit no VS2008 Test Runner</a></li>
<li><a href="http://seiti.eti.br/blog/2006/aspnet-development-server-integrated-web-server" rel="bookmark" title="19 de setembro de 2006">ASP.NET Development Server (integrated web server)</a></li>
<li><a href="http://seiti.eti.br/blog/2009/linq-to-sql" rel="bookmark" title="13 de abril de 2009">Linq to Sql</a></li>
</ul>
<p><!-- Similar Posts took 6.299 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2010/erro-no-deploy-automatico-hudson-versus-msbuild/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web Deployment Project e o Visual Studio 2008</title>
		<link>http://seiti.eti.br/blog/2010/web-deployment-project-e-o-visual-studio-2008</link>
		<comments>http://seiti.eti.br/blog/2010/web-deployment-project-e-o-visual-studio-2008#comments</comments>
		<pubDate>Mon, 12 Apr 2010 18:01:44 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[visual studio]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=1111</guid>
		<description><![CDATA[O Web Deployment Project é uma extensão do Visual Studio 2008 que permite a prévia compilação de páginas e controles de uma aplicação web. Assim podemos detectar se determinada página apresentará erro antes de algum usuário visitar a página em &#8230; <a href="http://seiti.eti.br/blog/2010/web-deployment-project-e-o-visual-studio-2008">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>O <a href="http://www.microsoft.com/downloads/details.aspx?familyId=0AA30AE8-C73B-4BDD-BB1B-FE697256C459&amp;displaylang=en">Web Deployment Project</a> é uma extensão do Visual Studio 2008 que permite a prévia compilação de páginas e controles de uma aplicação web. Assim podemos detectar se determinada página apresentará erro antes de algum usuário visitar a página em questão.</p>
<p>A parte chata é que isto impossbilita a edição das páginas e controles à quente, direto no servidor. Opa, na verdade esta é parte boa.</p>
<p>Após instalar basta clicar com o botão direito sobre o seu projeto no Visual Studio que surgirá uma opção <em>Add Web Deployment Project&#8230;</em>. Clicando nesta opção o projeto deveria ser criado. Deveria. Ao menos aqui no Windows 7 não funciona.</p>
<p>Um erro surge dizendo, entre outras coisas: <strong>Unable to create the project file</strong>. </p>
<p>Como solucionar?  Você deve rodar o Visual Studio como <strong>Administrador</strong>. Simples assim.
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2008/substituindo-texto-com-perl-e-estouro-de-pilha" rel="bookmark" title="29 de outubro de 2008">Substituindo texto com Perl e Estouro de Pilha</a></li>
<li><a href="http://seiti.eti.br/blog/2006/agrupando-arquivos-na-arvore-do-vs-2005" rel="bookmark" title="21 de dezembro de 2006">Agrupando arquivos na árvore do VS 2005</a></li>
<li><a href="http://seiti.eti.br/blog/2008/esquema-de-cores-para-o-visual-studio-2008" rel="bookmark" title="27 de outubro de 2008">Esquema de cores para o Visual Studio 2008</a></li>
</ul>
<p><!-- Similar Posts took 5.920 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2010/web-deployment-project-e-o-visual-studio-2008/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Login failed for user &#8216;NT AUTHORITY\NETWORK SERVICE&#8217;</title>
		<link>http://seiti.eti.br/blog/2010/login-failed-for-user-nt-authoritynetwork-service</link>
		<comments>http://seiti.eti.br/blog/2010/login-failed-for-user-nt-authoritynetwork-service#comments</comments>
		<pubDate>Wed, 31 Mar 2010 19:46:25 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[Sql Server]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=1104</guid>
		<description><![CDATA[Acabou de instalar o SQL Server? Surgiu um dos seguintes erros? Login failed for user &#8216;NT AUTHORITY\NETWORK SERVICE&#8217; ou Falha no login &#8216;AUTORIDADE NT\SERVIÇO DE REDE&#8217; Não se preocupe. Execute o seguinte no banco de dados master no SQL Server: &#8230; <a href="http://seiti.eti.br/blog/2010/login-failed-for-user-nt-authoritynetwork-service">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Acabou de instalar o SQL Server? Surgiu um dos seguintes erros?</p>
<blockquote><p>Login failed for user &#8216;NT AUTHORITY\NETWORK SERVICE&#8217;</p></blockquote>
<p>ou </p>
<blockquote><p>Falha no login &#8216;AUTORIDADE NT\SERVIÇO DE REDE&#8217;</p></blockquote>
<p>Não se preocupe. Execute o seguinte no banco de dados <strong>master</strong> no SQL Server:</p>
<pre class="brush: plain;">
sp_grantlogin 'NT AUTHORITY\NETWORK SERVICE'
</pre>
<p>ou</p>
<pre class="brush: plain;">
sp_grantlogin 'AUTORIDADE NT\SERVIÇO DE REDE'
</pre>
<p>Pronto, sua aplicação conversará com seu banco de dados.</p>
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2010/linked-server-consultando-o-postgresql-atraves-do-ms-sql-server" rel="bookmark" title="14 de março de 2010">Linked Server: consultando o PostGreSQL através do MS SQL Server</a></li>
<li><a href="http://seiti.eti.br/blog/2008/linked-server-com-oracle" rel="bookmark" title="2 de dezembro de 2008">Linked server com Oracle</a></li>
<li><a href="http://seiti.eti.br/blog/2006/acessando-o-ms-sql-server-atraves-do-postgresql" rel="bookmark" title="19 de setembro de 2006">Acessando o MS SQL Server através do PostGreSQL</a></li>
<li><a href="http://seiti.eti.br/blog/2008/linked-servers" rel="bookmark" title="27 de novembro de 2008">Linked Servers</a></li>
</ul>
<p><!-- Similar Posts took 5.756 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2010/login-failed-for-user-nt-authoritynetwork-service/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linked Server: consultando o PostGreSQL através do MS SQL Server</title>
		<link>http://seiti.eti.br/blog/2010/linked-server-consultando-o-postgresql-atraves-do-ms-sql-server</link>
		<comments>http://seiti.eti.br/blog/2010/linked-server-consultando-o-postgresql-atraves-do-ms-sql-server#comments</comments>
		<pubDate>Sun, 14 Mar 2010 19:51:57 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Sql Server]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=1083</guid>
		<description><![CDATA[Antes de tudo é necessário instalar os drivers ODBC do PostGreSQL no servidor em que se encontra o MS SQL Server. Depois registre um System DSN, ou Fonte de Dados do Sistema. Para isto basta se encaminhar para: Painel de &#8230; <a href="http://seiti.eti.br/blog/2010/linked-server-consultando-o-postgresql-atraves-do-ms-sql-server">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Antes de tudo é necessário instalar os <a href="http://www.postgresql.org/ftp/odbc/versions/msi/">drivers ODBC</a> do PostGreSQL no servidor em que se encontra o MS SQL Server.</p>
<p>Depois registre um <em>System DSN</em>, ou Fonte de Dados do Sistema. Para isto basta se encaminhar para:</p>
<blockquote><p>Painel de Controle → Ferramentas Administrativas → Fontes de Dados ODBC.</p></blockquote>
<p>Basta preencher as caixinhas e depois testar. Com a conexão funcionando,  agora é hora de se criar um <em>Linked Server</em> entre o MS SQL Server e o PostGreSQL.</p>
<pre class="brush: plain;">
EXEC master.dbo.sp_droplinkedsrvlogin
          @rmtsrvname=N'LINKEDSERVERNAME'
	, @locallogin=NULL

EXEC master.dbo.sp_dropserver
	  @server = 'LINKEDSERVERNAME'

EXEC master.dbo.sp_addlinkedserver
	  @server = 'LINKEDSERVERNAME'
	, @provider = 'Postgresql OLE DB'
	, @datasrc = 'Postgresql ANSI'

EXEC master.dbo.sp_addlinkedsrvlogin
	  @rmtsrvname=N'LINKEDSERVERNAME'
	, @useself=N'False'
	, @locallogin=NULL
	, @rmtuser='usuariopostgres'
	, @rmtpassword='senhapostgres'
</pre>
<p>Agora você pode fazer consultas assim:</p>
<pre class="brush: plain;">
SELECT * FROM openquery(LINKEDSERVERNAME, 'SELECT * FROM TABELADOPOSTGRES')
</pre>
</pre>
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2006/acessando-o-ms-sql-server-atraves-do-postgresql" rel="bookmark" title="19 de setembro de 2006">Acessando o MS SQL Server através do PostGreSQL</a></li>
<li><a href="http://seiti.eti.br/blog/2008/linked-server-com-oracle" rel="bookmark" title="2 de dezembro de 2008">Linked server com Oracle</a></li>
<li><a href="http://seiti.eti.br/blog/2010/login-failed-for-user-nt-authoritynetwork-service" rel="bookmark" title="31 de março de 2010">Login failed for user &#8216;NT AUTHORITY\NETWORK SERVICE&#8217;</a></li>
<li><a href="http://seiti.eti.br/blog/2008/linked-servers" rel="bookmark" title="27 de novembro de 2008">Linked Servers</a></li>
</ul>
<p><!-- Similar Posts took 5.960 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2010/linked-server-consultando-o-postgresql-atraves-do-ms-sql-server/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Funções Geoespaciais do MS SQL Server 2008</title>
		<link>http://seiti.eti.br/blog/2010/funcoes-geoespaciais-do-ms-sql-server-2008</link>
		<comments>http://seiti.eti.br/blog/2010/funcoes-geoespaciais-do-ms-sql-server-2008#comments</comments>
		<pubDate>Fri, 12 Mar 2010 21:24:28 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[arcgis]]></category>
		<category><![CDATA[geo]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=1078</guid>
		<description><![CDATA[O MS SQL Server 2008 (MSSQL) possui um tipo próprio para guardar geometrias: geometry (tem um geography também, mais útil para representar feições mais extensas). E ainda implementa os métodos definidos pela OGC. Isto possibilita operações CRUD sobre o dados &#8230; <a href="http://seiti.eti.br/blog/2010/funcoes-geoespaciais-do-ms-sql-server-2008">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>O MS SQL Server 2008 (MSSQL) possui um tipo  próprio para guardar geometrias: <a href="http://msdn.microsoft.com/en-us/library/cc280487.aspx"><em>geometry</em></a> (tem um <em>geography</em> também, mais útil para representar feições mais extensas).</p>
<p>E ainda <a href="http://msdn.microsoft.com/en-us/library/bb933973.aspx"> implementa</a> os métodos definidos pela OGC.</p>
<p>Isto  possibilita operações CRUD sobre o dados georreferenciados, diretamente através de  comandos SQL.</p>
<p>Os métodos estáticos, acessíveis através de <tt>geometry::NomeDoMétodo()</tt>,  são:</p>
<ul>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl00" href="http://msdn.microsoft.com/en-us/library/bb933823.aspx">STGeomFromText (geometry Data  Type)</a></li>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl01" href="http://msdn.microsoft.com/en-us/library/bb933821.aspx">STPointFromText (geometry Data  Type)</a></li>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl02" href="http://msdn.microsoft.com/en-us/library/bb933839.aspx">STLineFromText (geometry Data  Type)</a></li>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl03" href="http://msdn.microsoft.com/en-us/library/bb933922.aspx">STPolyFromText (geometry Data  Type)</a></li>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl04" href="http://msdn.microsoft.com/en-us/library/bb933833.aspx">STMPointFromText (geometry Data  Type)</a></li>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl05" href="http://msdn.microsoft.com/en-us/library/bb933836.aspx">STMLineFromText (geometry Data  Type)</a></li>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl06" href="http://msdn.microsoft.com/en-us/library/bb933986.aspx">STMPolyFromText (geometry Data  Type)</a></li>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl07" href="http://msdn.microsoft.com/en-us/library/bb933818.aspx">STGeomCollFromText (geometry  Data Type)</a></li>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl08" href="http://msdn.microsoft.com/en-us/library/bb933882.aspx">STGeomFromWKB (geometry Data  Type)</a></li>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl09" href="http://msdn.microsoft.com/en-us/library/bb933813.aspx">STPointFromWKB (geometry Data  Type)</a></li>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl10" href="http://msdn.microsoft.com/en-us/library/bb933980.aspx">STLineFromWKB (geometry Data  Type)</a></li>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl11" href="http://msdn.microsoft.com/en-us/library/bb933907.aspx">STPolyFromWKB (geometry Data  Type)</a></li>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl12" href="http://msdn.microsoft.com/en-us/library/bb933801.aspx">STMPointFromWKB (geometry Data  Type)</a></li>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl13" href="http://msdn.microsoft.com/en-us/library/bb933800.aspx">STMLineFromWKB (geometry Data  Type)</a></li>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl14" href="http://msdn.microsoft.com/en-us/library/bb933964.aspx">STMPolyFromWKB (geometry Data  Type)</a></li>
<li><a id="ctl00_MainContent_ctl27_ctl00_ctl15" href="http://msdn.microsoft.com/en-us/library/bb933889.aspx">STGeomCollFromWKB (geometry  Data Type)</a></li>
</ul>
<p>E os métodos do objeto <em>geometry</em>:</p>
<ul>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl00" href="http://msdn.microsoft.com/en-us/library/bb933923.aspx">STArea</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl01" href="http://msdn.microsoft.com/en-us/library/bb933881.aspx">STAsBinary</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl02" href="http://msdn.microsoft.com/en-us/library/bb933977.aspx">STAsText</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl03" href="http://msdn.microsoft.com/en-us/library/bb933985.aspx">STBoundary</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl04" href="http://msdn.microsoft.com/en-us/library/bb933963.aspx">STBuffer</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl05" href="http://msdn.microsoft.com/en-us/library/bb933847.aspx">STCentroid</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl06" href="http://msdn.microsoft.com/en-us/library/bb933904.aspx">STContains</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl07" href="http://msdn.microsoft.com/en-us/library/bb933878.aspx">STConvexHull</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl08" href="http://msdn.microsoft.com/en-us/library/bb933838.aspx">STCrosses</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl09" href="http://msdn.microsoft.com/en-us/library/bb933893.aspx">STDifference</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl10" href="http://msdn.microsoft.com/en-us/library/bb933848.aspx">STDimension</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl11" href="http://msdn.microsoft.com/en-us/library/bb933909.aspx">STDisjoint</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl12" href="http://msdn.microsoft.com/en-us/library/bb933952.aspx">STDistance</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl13" href="http://msdn.microsoft.com/en-us/library/bb933879.aspx">STEndpoint</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl14" href="http://msdn.microsoft.com/en-us/library/bb933896.aspx">STEnvelope</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl15" href="http://msdn.microsoft.com/en-us/library/bb933902.aspx">STEquals</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl16" href="http://msdn.microsoft.com/en-us/library/bb933955.aspx">STExteriorRing</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl17" href="http://msdn.microsoft.com/en-us/library/bb933831.aspx">STGeometryN</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl18" href="http://msdn.microsoft.com/en-us/library/bb933825.aspx">STGeometryType</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl19" href="http://msdn.microsoft.com/en-us/library/bb933843.aspx">STInteriorRingN</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl20" href="http://msdn.microsoft.com/en-us/library/bb933832.aspx">STIntersection</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl21" href="http://msdn.microsoft.com/en-us/library/bb933899.aspx">STIntersects</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl22" href="http://msdn.microsoft.com/en-us/library/bb933815.aspx">STIsClosed</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl23" href="http://msdn.microsoft.com/en-us/library/bb933975.aspx">STIsEmpty</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl24" href="http://msdn.microsoft.com/en-us/library/bb933982.aspx">STIsRing</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl25" href="http://msdn.microsoft.com/en-us/library/bb933974.aspx">STIsSimple</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl26" href="http://msdn.microsoft.com/en-us/library/bb933890.aspx">STIsValid</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl27" href="http://msdn.microsoft.com/en-us/library/bb933978.aspx">STLength</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl28" href="http://msdn.microsoft.com/en-us/library/bb933910.aspx">STNumGeometries</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl29" href="http://msdn.microsoft.com/en-us/library/bb933845.aspx">STNumInteriorRing</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl30" href="http://msdn.microsoft.com/en-us/library/bb933916.aspx">STNumPoints</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl31" href="http://msdn.microsoft.com/en-us/library/bb933817.aspx">STOverlaps</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl32" href="http://msdn.microsoft.com/en-us/library/bb933908.aspx">STPointN</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl33" href="http://msdn.microsoft.com/en-us/library/bb933826.aspx">STPointOnSurface</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl34" href="http://msdn.microsoft.com/en-us/library/bb933915.aspx">STRelate</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl35" href="http://msdn.microsoft.com/en-us/library/bb933851.aspx">STSrid</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl36" href="http://msdn.microsoft.com/en-us/library/bb933804.aspx">STStartPoint</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl37" href="http://msdn.microsoft.com/en-us/library/bb933820.aspx">STSymDifference</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl38" href="http://msdn.microsoft.com/en-us/library/bb933953.aspx">STTouches</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl39" href="http://msdn.microsoft.com/en-us/library/bb933850.aspx">STUnion</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl40" href="http://msdn.microsoft.com/en-us/library/bb933991.aspx">STWithin</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl41" href="http://msdn.microsoft.com/en-us/library/bb933828.aspx">STX</a></li>
<li><a id="ctl00_MainContent_ctl54_ctl00_ctl42" href="http://msdn.microsoft.com/en-us/library/bb933990.aspx">STY</a></li>
</ul>
<p>Estes métodos podem ser chamados da seguinte forma, por exemplo:</p>
<pre class="brush: plain;">

SELECT coluna1.STArea() FROM tabela
</pre>
<p>onde <tt>coluna1</tt> é do tipo <em>geometry</em>.
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2010/inserindo-registro-geoespaciais-arcsde-e-sql-server" rel="bookmark" title="10 de março de 2010">Inserindo registros geoespaciais: ArcSDE e SQL Server</a></li>
<li><a href="http://seiti.eti.br/blog/2009/arcsde-e-ms-sql-server-2008" rel="bookmark" title="23 de outubro de 2009">ArcSDE e MS SQL Server 2008</a></li>
<li><a href="http://seiti.eti.br/blog/2009/arcgis-javascript-dojo-e-o-metodo-require" rel="bookmark" title="16 de setembro de 2009">ArcGIS Javascript, Dojo e o método require</a></li>
<li><a href="http://seiti.eti.br/blog/2008/sig-sistema-de-informacao-geografica" rel="bookmark" title="23 de abril de 2008">SIG &#8211; Sistema de Informação Geográfica</a></li>
</ul>
<p><!-- Similar Posts took 8.366 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2010/funcoes-geoespaciais-do-ms-sql-server-2008/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Inserindo registros geoespaciais: ArcSDE e SQL Server</title>
		<link>http://seiti.eti.br/blog/2010/inserindo-registro-geoespaciais-arcsde-e-sql-server</link>
		<comments>http://seiti.eti.br/blog/2010/inserindo-registro-geoespaciais-arcsde-e-sql-server#comments</comments>
		<pubDate>Wed, 10 Mar 2010 21:13:34 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[arcgis]]></category>
		<category><![CDATA[geo]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=1070</guid>
		<description><![CDATA[Inserir registros diretamente através de comandos SQL é bem simples. Note que estou usando como tipo de dado geoespacial o GEOMETRY, nativo do SQL Server 2008. Primeiro  é necessário criar uma tabela no SQL Server e registrá-la junto ao ArcSDE. &#8230; <a href="http://seiti.eti.br/blog/2010/inserindo-registro-geoespaciais-arcsde-e-sql-server">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Inserir registros diretamente através de comandos SQL é bem simples. Note que estou usando como tipo de dado geoespacial o <a href="http://seiti.eti.br/blog/2009/arcsde-e-ms-sql-server-2008">GEOMETRY</a>, nativo do SQL Server 2008.</p>
<p>Primeiro  é necessário criar uma tabela no SQL Server e registrá-la junto ao ArcSDE. Isto é bem simples de se realizar utilizando o ArcCatalog (note que também dá para se criar a tabela via SQL e registrá-la no ArcSDE via linha de comando).  Basta entrar no ArcCatalog, conectar-se com sua instância do ArcSDE e clicar com o botão direito no ícone do banco de dados. Depois é só escolher o <em>Feature Class</em>:</p>
<div class="wp-caption aligncenter" style="width: 343px"><a title="Feature Class by Seiti Yamashiro, on Flickr" href="http://www.flickr.com/photos/seiti/4423382146/"><img title="Criando um Feature Class" src="http://farm5.static.flickr.com/4068/4423382146_547ffd9792.jpg" alt="Feature Class" width="333" height="376" /></a><p class="wp-caption-text">Criando um Feature Class</p></div>
<p>É apresentada então uma caixa de diálogo para criar sua tabela que conterá sua feição. Criei uma tabela chamada <em>MeuFeatureClass</em>. As colunas <strong>OBJECTID</strong> e <strong>SHAPE</strong> são criadas por padrão. Adicionei um <strong>campo1</strong> e um <strong>campo2</strong> também. E escolhi o tipo da geometria como <em>POINT</em>.</p>
<p>Criada a tabela é bem simples de se inserir um registro através de comando SQL:</p>
<pre class="brush: plain;">
INSERT INTO
MeuBD.sde.MeuFeatureClass
(OBJECTID, campo1, campo2, shape)
VALUES
(1, valor1, valor2, geometry::STGeomFromText('POINT (-46.616667 -23.533333)', 4674))
</pre>
<p>O comando acima insere um registro na tabela contendo um ponto localizado no município de São Paulo &#8211; SP, usando o SRID 4674 (<a href="http://seiti.eti.br/blog/2010/sirgas-2000">SIRGAS 2000</a>).</p>
<p>Note que não usamos uma função típica do T-SQL  para transformar o texto dado em uma coordenada válida pro sistema.  Isto me deixou confuso no início, pois eu não encontrava funções geoespaciais no banco de dados. Liste as funções existentes no banco de dados do ArcSDE que oê não encontrará nada relacionado ao sistema geo.</p>
<p>Estas funções ficam disponíveis como métodos da classe e objetos  <strong><em>geometry</em></strong>.  No caso acima, o <tt>STGeomFromText</tt> é um método estático da classe <tt>geometry</tt>. Os mundos da Orientação a Objetos e do SQL se mesclam cada vez mais&#8230;
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2009/arcsde-e-ms-sql-server-2008" rel="bookmark" title="23 de outubro de 2009">ArcSDE e MS SQL Server 2008</a></li>
<li><a href="http://seiti.eti.br/blog/2010/funcoes-geoespaciais-do-ms-sql-server-2008" rel="bookmark" title="12 de março de 2010">Funções Geoespaciais do MS SQL Server 2008</a></li>
<li><a href="http://seiti.eti.br/blog/2008/sig-sistema-de-informacao-geografica" rel="bookmark" title="23 de abril de 2008">SIG &#8211; Sistema de Informação Geográfica</a></li>
<li><a href="http://seiti.eti.br/blog/2010/cache-camadas-no-arcgis-server" rel="bookmark" title="8 de fevereiro de 2010">Cache e camadas no ArcGIS Server</a></li>
</ul>
<p><!-- Similar Posts took 8.724 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2010/inserindo-registro-geoespaciais-arcsde-e-sql-server/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Carregando bibliotecas Javascript abertas</title>
		<link>http://seiti.eti.br/blog/2010/carregando-bibliotecas-javascript-abertas</link>
		<comments>http://seiti.eti.br/blog/2010/carregando-bibliotecas-javascript-abertas#comments</comments>
		<pubDate>Fri, 05 Feb 2010 15:49:34 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=44</guid>
		<description><![CDATA[Ext, jQuery, prototype, MooTools, Dojo, scrip.taculo.us, YUI. São algumas das feras que um desenvolvedor web tem de enfrentar, no caminho para matar o Dragão. Algo que pode ajudar nesta tarefa é usar a própria API Google para carregar estas outras &#8230; <a href="http://seiti.eti.br/blog/2010/carregando-bibliotecas-javascript-abertas">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ext, jQuery, prototype, MooTools, Dojo, scrip.taculo.us, YUI. São algumas das feras que um desenvolvedor web tem de enfrentar, no caminho para <a href="http://www.scribd.com/doc/320372/How-to-kill-a-Dragon-with-Programming">matar o Dragão</a>.</p>
<p>Algo que pode ajudar nesta tarefa é usar a própria API Google para carregar estas outras APIs:</p>
<p><a href="http://code.google.com/apis/ajaxlibs/">http://code.google.com/apis/ajaxlibs/</a></p>
<p>O código, retirado direto do site, é o seguinte:</p>
<pre class="brush: plain;">
// Load Google JS API
&lt;script src=&quot;http://www.google.com/jsapi&quot;&gt;&lt;/script&gt;
&lt;script&gt;
// Load jQuery
google.load(&quot;jquery&quot;, &quot;1&quot;);
&lt;/script&gt;
</pre>
<p>Você simplesmente:</p>
<ul>
<li>carrega a API javascript do Google;</li>
<li>utiliza a API do Google para carregar as outras APIs, podendo escolher a versão, inclusive.</li>
</ul>
<p>A opção de escolher a versão do script ajuda bastante a manter seus sistemas atualizados de forma bem simples.</p>
<p>O problema é apenas não poder guardar as APIs no servidor. Em uma rede local sem acesso à internet, por exemplo, isto já não serve.
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2009/arcgis-javascript-dojo-e-o-metodo-require" rel="bookmark" title="16 de setembro de 2009">ArcGIS Javascript, Dojo e o método require</a></li>
<li><a href="http://seiti.eti.br/blog/2009/ext-js" rel="bookmark" title="12 de maio de 2009">Ext JS</a></li>
<li><a href="http://seiti.eti.br/blog/2009/type-casting-no-javascript" rel="bookmark" title="11 de maio de 2009">Type &#8220;casting&#8221; no Javascript</a></li>
<li><a href="http://seiti.eti.br/blog/2008/campo-datefield-em-um-formulario-extjs" rel="bookmark" title="24 de julho de 2008">Campo DateField em um formulário ExtJS</a></li>
</ul>
<p><!-- Similar Posts took 6.973 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2010/carregando-bibliotecas-javascript-abertas/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SIRGAS 2000</title>
		<link>http://seiti.eti.br/blog/2010/sirgas-2000</link>
		<comments>http://seiti.eti.br/blog/2010/sirgas-2000#comments</comments>
		<pubDate>Wed, 27 Jan 2010 16:50:32 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[geo]]></category>
		<category><![CDATA[gis]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=951</guid>
		<description><![CDATA[Antes Sistema de Referencia Geocéntrico para America del Sur e agora Sistema de Referencia Geocéntrico para las Américas, o SIRGAS é o sistema de referenciamento espacial padrão do Brasil, definido pelo IBGE. Seu SRID, num sistema geográfico, é  EPSG:  4674: &#8230; <a href="http://seiti.eti.br/blog/2010/sirgas-2000">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Antes <em>Sistema de Referencia Geocéntrico para America del Sur</em> e agora <em>Sistema de Referencia Geocéntrico para las Américas</em>, o <a href="http://www.sirgas.org">SIRGAS</a> é o <a href="http://seiti.eti.br/blog/2010/sistema-de-referenciamento-espacial">sistema de referenciamento espacial</a> padrão do Brasil, definido pelo <a href="http://www.ibge.gov.br/sirgas/">IBGE</a>.</p>
<p>Seu SRID, num<a href="http://seiti.eti.br/blog/2010/sistema-de-referenciamento-espacial"> sistema geográfico</a>, é  <a href="http://www.spatialreference.org/ref/epsg/4674/">EPSG:  4674</a>:</p>
<pre class="brush: plain;">
GEOGCS[&quot;SIRGAS 2000&quot;,
    DATUM[&quot;Sistema_de_Referencia_Geocentrico_para_America_del_Sur_2000&quot;,
        SPHEROID[&quot;GRS 1980&quot;,6378137,298.257222101,
            AUTHORITY[&quot;EPSG&quot;,&quot;7019&quot;]],
        TOWGS84[0,0,0,0,0,0,0],
        AUTHORITY[&quot;EPSG&quot;,&quot;6674&quot;]],
    PRIMEM[&quot;Greenwich&quot;,0,
        AUTHORITY[&quot;EPSG&quot;,&quot;8901&quot;]],
    UNIT[&quot;degree&quot;,0.01745329251994328,
        AUTHORITY[&quot;EPSG&quot;,&quot;9122&quot;]],
    AUTHORITY[&quot;EPSG&quot;,&quot;4674&quot;]]
</pre>
<p>Na prática o SIRGAS utiliza <strong>o mesmo</strong> elipsóde de referência do WGS84 &#8211; <em>GRS 1980</em>. Veja mais no <a href="http://www6.ufrgs.br/engcart/Teste/refer_exp.html">site da UFRGS</a>. O mesmo ocorre com o <strong>posicionamento</strong> do elipsóide, com seus centros situando-se bem próximos um do outro.</p>
<p>Isto significa que as medidas dados pelo SIRGAS são quase iguais aos dados pelo WGS84,  onde uma diferença entre as medidas pode ser menor que o erro aproximado de seu instrumento GPS, pois esta diferença está na ordem de centímetros.</p>
<p>Assim, se seu equipamento for antigo é bem provável que ocorram duas coisas:</p>
<ul>
<li>ele não tenha uma precisão tão boa a ponto de se distinguir entre WGS84 e SIRGAS 2000;</li>
<li>ele não possua o SIRGAS 2000 em seu rol de referências.</li>
</ul>
<p>Então use o WGS84 e seja feliz.
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2010/sistema-de-referenciamento-espacial" rel="bookmark" title="18 de janeiro de 2010">Sistema de Referenciamento Espacial</a></li>
<li><a href="http://seiti.eti.br/blog/2008/sig-sistema-de-informacao-geografica" rel="bookmark" title="23 de abril de 2008">SIG &#8211; Sistema de Informação Geográfica</a></li>
<li><a href="http://seiti.eti.br/blog/2009/arcsde-e-ms-sql-server-2008" rel="bookmark" title="23 de outubro de 2009">ArcSDE e MS SQL Server 2008</a></li>
<li><a href="http://seiti.eti.br/blog/2010/inserindo-registro-geoespaciais-arcsde-e-sql-server" rel="bookmark" title="10 de março de 2010">Inserindo registros geoespaciais: ArcSDE e SQL Server</a></li>
</ul>
<p><!-- Similar Posts took 9.126 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2010/sirgas-2000/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Sistema de Referenciamento Espacial</title>
		<link>http://seiti.eti.br/blog/2010/sistema-de-referenciamento-espacial</link>
		<comments>http://seiti.eti.br/blog/2010/sistema-de-referenciamento-espacial#comments</comments>
		<pubDate>Mon, 18 Jan 2010 20:19:09 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[geo]]></category>
		<category><![CDATA[gis]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=934</guid>
		<description><![CDATA[Spatial Reference System,  ou Sistema de Referenciamento Espacial, define como descrever uma posição, uma localização no espaço. Para determinarmos essa posição precisamos de duas coisas: um ponto de referência e um sistema de coordenadas. Datum Para descrever esta localização temos &#8230; <a href="http://seiti.eti.br/blog/2010/sistema-de-referenciamento-espacial">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><em>Spatial Reference System</em>,  ou Sistema de Referenciamento Espacial, define como descrever uma posição, uma localização no espaço.</p>
<p>Para determinarmos essa posição precisamos de duas coisas: um ponto de referência e um sistema de coordenadas.</p>
<h2><em>Datum</em></h2>
<p>Para descrever esta localização temos de levar em conta algumas coisas. Primeiro, a Terra não é plana. Verdade. E nem uma bola.  Mas podemos aproximar sua superfície à algumas formas geométricas.  A primeira que vem à mente é a <strong>esfera</strong>. É boa para se montar globos escolares e pintar os continentes em  bolas de  praia. Mas, como aprendemos na escolinha, a Terra é achatada nos pólos. Mas a aproximação com a esfera serve para qualquer coisa que conte com uma escala pequena.</p>
<p style="text-align: center;">
<div class="wp-caption aligncenter" style="width: 390px"><a href="http://pt.wikipedia.org/wiki/Ficheiro:GEO_Globe.jpg"><img src="http://upload.wikimedia.org/wikipedia/commons/9/9f/GEO_Globe.jpg" alt="" width="380" height="400" /></a><p class="wp-caption-text">Globo terrestre</p></div>
<p>Segue então uma segunda aproximação: um <strong>elipsóide ou esferóide</strong>. Ou uma esfera achatada.  Esta forma geométrica é bastante utilizada para descrever a superfície do planeta,  parte por facilitar bastante os cálculos envolvidos e parte por se adequar razoavelmente à superfície verdadeira da Terra. Para obter um grau maior de aproximação modificamos os tamanhos dos eixos do elipsóide e também deslocamos seu centro, ajeitando-o com relação à Terra.</p>
<p>Ou seja, se a Terra fosse um esferóide perfeito, todos os pontos de sua superfície iriam tocar nos pontos do esferóide de referência.  Como isso não ocorre, a gente ajeita o esferóide, <em>definindo em que pontos</em> o esferóide toca a superfície do planeta.  Note que definição de pontos tem <em>data de validade</em>, ou pelo menos data de referência, visto que a <a href="http://pt.wikipedia.org/wiki/Deriva_continental">posição relativa entre os continentes muda com o tempo</a>. Digamos que nosso esferóide toca a superfície do planeta em um ponto específico de Pindamonhangaba e em outro em Paris. Infelizmente estes pontos não corresponderão exatamente ao mesmo local no dia seguinte. Por isso temos nomes como WGS84, SAD69. Os números se referem ao ano .</p>
<div class="wp-caption aligncenter" style="width: 393px"><a href="http://pt.wikipedia.org/wiki/Ficheiro:OblateSpheroid.PNG"><img src="http://upload.wikimedia.org/wikipedia/commons/b/b5/OblateSpheroid.PNG" alt="" width="383" height="294" /></a><p class="wp-caption-text">Esferóide</p></div>
<p>Uma outra forma é a <strong>geóide</strong>. A geóide se trata de uma figura geométrica cuja superfície possui sempre a mesma força gravitacional, correspondendo mais ou menos ao nível médio do mar. Uma esfera não rolaria para lado nenhum em cima da superfície de uma geóide. Os cálculos sobre esta figura são mais complicados, mas é uma aproximação bastante útil para analisar a construção de canais, rodovias extensas e redes de água e esgoto.</p>
<div class="wp-caption aligncenter" style="width: 500px"><a href="http://pt.wikipedia.org/wiki/Ficheiro:Geoids_sm.jpg"><img src="http://upload.wikimedia.org/wikipedia/commons/5/56/Geoids_sm.jpg" alt="" width="490" height="230" /></a><p class="wp-caption-text">Geóide</p></div>
<p>A escolha da figura geométrica, a definição de suas dimensões e o posicionamento desta figura com relação à Terra nos dá o <em><strong>datum</strong></em> (nota: só estou considerando sistema geocêntricos, deixando os topocêntricos de lado).</p>
<div class="wp-caption aligncenter" style="width: 410px"><a href="http://en.wikipedia.org/wiki/File:Sperm-egg.jpg"><img src="http://upload.wikimedia.org/wikipedia/commons/8/86/Sperm-egg.jpg" alt="" width="400" height="274" /></a><p class="wp-caption-text">Espermatozóide</p></div>
<p style="text-align: center;">
<h2>Sistema Geográfico de Coordenadas</h2>
<p>Temos um <em>datum</em>. Mas isto não basta. Precisamos de um sistema de coordenadas para localizar o que quer que seja. Para isto temos um Sistema Geográfico de Coordenadas (<em>geographic coordinate system</em> ou <strong>GCS</strong>), também conhecido como sistema <strong>esférico</strong> de coordenadas,  que inclui uma unidade de medida angular, um meridiano principal e um <em>datum</em>.</p>
<div class="wp-caption aligncenter" style="width: 330px"><a href="http://en.wikipedia.org/wiki/File:Geographic_coordinates_sphere.svg"><img class=" " src="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Geographic_coordinates_sphere.svg/500px-Geographic_coordinates_sphere.svg.png" alt="" width="320" height="315" /></a><p class="wp-caption-text">Latitude (φ) e Longitude (λ)</p></div>
<p>Com o <em>datum</em>, o equador e o meridiano principal, geralmente o de <em>Greenwich</em>, conseguimos um ponto de referência,  onde φ = 0° e λ = 0°,  e o centro do esferóide, a partir do qual todas as medidas são baseadas. Só para constar, a cidade de São Paulo se encontra em <tt>23°33′0″ S, 46°38′0″ W</tt>, ou seja, latitude  <tt>-23°33′0″</tt> e longitude<tt> -46°38′0″</tt>.</p>
<h2>Sistema de Coordenadas Projetadas</h2>
<p>O GCS ajuda a localizar algum ponto. Mas para visualizar o mapa no papel, ou na tela do computador, precisamos levar tudo que está em um objeto 3D em pontos correspondentes em um plano 2D. Isto se chama <strong>projeção</strong>. A mesma projeção que se ensina nas aulas de matemática da escolinha, mas <a href="http://en.wikipedia.org/wiki/Map_projection">aplicada em nossos mapas</a>.</p>
<p>Pensando na superfície da Terra, podemos pensar em algumas características:</p>
<ul>
<li>Área</li>
<li>Forma</li>
<li>Direção</li>
<li>Posicionamento relativo</li>
<li>Distância</li>
<li>Escala</li>
</ul>
<p>Quando projetamos esta superfície em um plano, podemos preservar algumas delas. Mas não todas. Por isto existem vários tipos de projeção. Cada uma prioriza alguma das propriedades descritas. A mais famosa é a Projeção de Mercator, que privilegia direção e posicionamento relativo.</p>
<div class="wp-caption aligncenter" style="width: 474px"><a href="http://en.wikipedia.org/wiki/File:Mercator-projection.jpg"><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/74/Mercator-projection.jpg/773px-Mercator-projection.jpg" alt="" width="464" height="359" /></a><p class="wp-caption-text">Projeção de Mercator</p></div>
<p>A projeção de Mercator é do tipo cilíndrica. Pense em uma bola de tênis enfiada em uma lata de batatas Pringles.  O problema dela é que deforma bastante a área conforme nos afastamos da linha do Equador. É só reparar no tamanho da Ántártica, que não é nem o dobro da do Brasil.</p>
<p>O cilindro em que é projetado o mapa tem seu eixo na mesma direção do eixo de rotação da Terra,  ou seja, o cilindro toca a Terra ao longo da linha do Equador.</p>
<p style="text-align: center;">
<div class="wp-caption aligncenter" style="width: 275px"><a href="http://webhelp.esri.com/arcgisdesktop/9.2/index.cfm?TopicName=About_map_projections"><img src="http://webhelp.esri.com/arcgisdesktop/9.2/published_images/lightbulb.gif" alt="" width="265" height="219" /></a><p class="wp-caption-text">Projeção cilíndrica</p></div>
<p>Isto nos leva à outra projeção importante: o Sistema Universal Transverso de Mercator (<strong>UTM</strong>). Ele é bastante semelhante à projeção de Mercator tradicional.</p>
<p>As diferenças são que o eixo do cilindro faz 90° com o eixo de rotação da Terra e o próprio cilindro é rotacionado  para obtermos projeções  mais precisas em cada fatia em que o cilindro toca a Terra.</p>
<div id="attachment_941" class="wp-caption aligncenter" style="width: 541px"><a href="http://www.swisstopo.admin.ch/internet/swisstopo/en/home/topics/survey/sys/refsys/projections.html"><img class="size-full wp-image-941" title="projections.parsys.19330.Image" src="http://seiti.eti.br/blog/wp-content/uploads/2010/01/projections.parsys.19330.Image_.gif" alt="" width="531" height="376" /></a><p class="wp-caption-text">Universal Transverse of Mercator</p></div>
<p>Estas fatias são então quadriculadas em uma grade. Cada quadrado desta grade forma então um sistema de coordenadas cartesianas, onde a unidade de medida é o <strong>metro</strong>.</p>
<h2>Sistema de Referenciamento Espacial (Spatial Reference System)</h2>
<p>E por fim temos o sistema de referencimento espacial, que nada mais é que a descrição de um conjunto que tem tudo que esta aí em cima. Um exemplo:</p>
<pre class="brush: plain;">
GEOGCS[&quot;SAD69&quot;,
    DATUM[&quot;South_American_Datum_1969&quot;,
        SPHEROID[&quot;GRS 1967 (SAD69)&quot;,6378160,298.25,
            AUTHORITY[&quot;EPSG&quot;,&quot;7050&quot;]],
        AUTHORITY[&quot;EPSG&quot;,&quot;6618&quot;]],
    PRIMEM[&quot;Greenwich&quot;,0,
        AUTHORITY[&quot;EPSG&quot;,&quot;8901&quot;]],
    UNIT[&quot;degree&quot;,0.01745329251994328,
        AUTHORITY[&quot;EPSG&quot;,&quot;9122&quot;]],
    AUTHORITY[&quot;EPSG&quot;,&quot;4618&quot;]]
</pre>
<p>O que é descrito acima, num formato conhecido como <em>Well Known Text</em> (WKT),  é o sistema SAD 69. Note é descrito o sistema geográfico de coordenadas (<strong>GEOGCS</strong>) com o <em>datum</em> utilizado,  o meridiano principal &#8211; Greenwich e a unidade de medida &#8211; <em>degree</em>,  assim como outras informações.  É comum utilizar apenas um número para nos referir a esta referência espacial. Este número, o <a href="http://en.wikipedia.org/wiki/SRID">SRID</a>,  pode ser visto na última linha: <strong>EPSG 4618.</strong> Muito mais exemplos em <a href="http://www.spatialreference.org/">SpatialReference.org</a>.</p>
<p>Outro exemplo:</p>
<pre class="brush: plain;">
PROJCS[&quot;SIRGAS 2000 / UTM zone 23S&quot;,
    GEOGCS[&quot;SIRGAS 2000&quot;,
        DATUM[&quot;Sistema_de_Referencia_Geocentrico_para_America_del_Sur_2000&quot;,
            SPHEROID[&quot;GRS 1980&quot;,6378137,298.257222101,
                AUTHORITY[&quot;EPSG&quot;,&quot;7019&quot;]],
            TOWGS84[0,0,0,0,0,0,0],
            AUTHORITY[&quot;EPSG&quot;,&quot;6674&quot;]],
        PRIMEM[&quot;Greenwich&quot;,0,
            AUTHORITY[&quot;EPSG&quot;,&quot;8901&quot;]],
        UNIT[&quot;degree&quot;,0.01745329251994328,
            AUTHORITY[&quot;EPSG&quot;,&quot;9122&quot;]],
        AUTHORITY[&quot;EPSG&quot;,&quot;4674&quot;]],
    UNIT[&quot;metre&quot;,1,
        AUTHORITY[&quot;EPSG&quot;,&quot;9001&quot;]],
    PROJECTION[&quot;Transverse_Mercator&quot;],
    PARAMETER[&quot;latitude_of_origin&quot;,0],
    PARAMETER[&quot;central_meridian&quot;,-45],
    PARAMETER[&quot;scale_factor&quot;,0.9996],
    PARAMETER[&quot;false_easting&quot;,500000],
    PARAMETER[&quot;false_northing&quot;,10000000],
    AUTHORITY[&quot;EPSG&quot;,&quot;31983&quot;],
    AXIS[&quot;Easting&quot;,EAST],
    AXIS[&quot;Northing&quot;,NORTH]]
</pre>
<p>Neste caso é descrito um sistema de coordenadas projetadas (<strong>PROJCS</strong>), o que requer, além das informações previstas para o GEOGCS, qual o tipo de projeção &#8211; <em>Transverse Mercator</em> &#8211; e localização do ponto de referência  que determina o origem do sistema de medidas, no caso  em metros.  O srid é <strong>31983.</strong></p>
<p>Ao invés de passar toda estas informações para alguém, basta informar o SRID.  Finalmente sabemos de onde vem o tal SRID que popula nossos banco de dados geográficos, e que devemos passar como parâmetro para as APIs Geo deste  mundão esferóide afora.
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2010/sirgas-2000" rel="bookmark" title="27 de janeiro de 2010">SIRGAS 2000</a></li>
<li><a href="http://seiti.eti.br/blog/2009/arcsde-e-ms-sql-server-2008" rel="bookmark" title="23 de outubro de 2009">ArcSDE e MS SQL Server 2008</a></li>
<li><a href="http://seiti.eti.br/blog/2008/sig-sistema-de-informacao-geografica" rel="bookmark" title="23 de abril de 2008">SIG &#8211; Sistema de Informação Geográfica</a></li>
<li><a href="http://seiti.eti.br/blog/2010/inserindo-registro-geoespaciais-arcsde-e-sql-server" rel="bookmark" title="10 de março de 2010">Inserindo registros geoespaciais: ArcSDE e SQL Server</a></li>
</ul>
<p><!-- Similar Posts took 9.648 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2010/sistema-de-referenciamento-espacial/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>O Menu Asp.NET e o Chrome (e Safari)</title>
		<link>http://seiti.eti.br/blog/2010/o-menu-asp-net-e-o-chrome-e-safari</link>
		<comments>http://seiti.eti.br/blog/2010/o-menu-asp-net-e-o-chrome-e-safari#comments</comments>
		<pubDate>Mon, 11 Jan 2010 18:52:08 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=928</guid>
		<description><![CDATA[Existe um problema no controle Menu no Asp.NET WebForms que faz com que ele não seja renderizado corretamente no Safari e no Google Chrome. O que acontece é que o servidor detecta o user-agent do navegador do cliente e monta &#8230; <a href="http://seiti.eti.br/blog/2010/o-menu-asp-net-e-o-chrome-e-safari">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Existe um problema no controle Menu no Asp.NET WebForms que faz com que ele não seja renderizado corretamente no Safari e no Google Chrome. O que acontece é que o servidor detecta o <em>user-agent</em> do navegador do cliente e monta a página de acordo.  Mas o  Asp.NET não reconhece o Safari e o Chrome como<strong> navegadores capazes</strong>, e por isso não conseguem renderizar um Menu em toda sua glória infestada de table&#8217;s, tr&#8217;s e td&#8217;s. Então lhes é servido um menu mais pobre, feio e maltratado .</p>
<p>O jeito é então alertar o Asp.NET  da existência destes navegadores.  E para isto basta criar uma pasta e um arquivo.</p>
<p>Se já não existir, crie em seu projeto uma pasta <em>App_Browsers</em>. E dentro dela crie um arquivo chamado <em>safari.browser</em>, que deve conter o seguinte:</p>
<pre class="brush: plain;">
&lt;browsers&gt;
    &lt;browser refID=&quot;Safari1Plus&quot;&gt;
        &lt;controlAdapters&gt;
            &lt;adapter controlType=&quot;System.Web.UI.WebControls.Menu&quot; adapterType=&quot;&quot; /&gt;
        &lt;/controlAdapters&gt;
    &lt;/browser&gt;
&lt;/browsers&gt;
</pre>
<p>E pronto! Tanto Safari quanto Chrome agora poderão mostrar seus lindos menus <em>tablefull.</em>
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2009/problema-rodando-testes-mbunit-no-vs2008-test-runner" rel="bookmark" title="3 de agosto de 2009">Problema rodando testes MbUnit no VS2008 Test Runner</a></li>
<li><a href="http://seiti.eti.br/blog/2006/aspnet-development-server-integrated-web-server" rel="bookmark" title="19 de setembro de 2006">ASP.NET Development Server (integrated web server)</a></li>
<li><a href="http://seiti.eti.br/blog/2009/httppostedfile-ie-versus-firefox" rel="bookmark" title="17 de maio de 2009">HttpPostedFile: IE versus Firefox</a></li>
<li><a href="http://seiti.eti.br/blog/2008/criando-um-metodo-de-log-em-aspnet" rel="bookmark" title="28 de agosto de 2008">Criando um método de log em Asp.NET</a></li>
</ul>
<p><!-- Similar Posts took 6.442 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2010/o-menu-asp-net-e-o-chrome-e-safari/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Programar é arte</title>
		<link>http://seiti.eti.br/blog/2009/programar-e-arte</link>
		<comments>http://seiti.eti.br/blog/2009/programar-e-arte#comments</comments>
		<pubDate>Fri, 18 Sep 2009 00:38:55 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[arte]]></category>
		<category><![CDATA[pensamento]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[texto]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=796</guid>
		<description><![CDATA[O tema é recorrente.  Desde o monumental The Art of Computer Programming ao, hmm&#8230;, pragmático  The Pragmatic Programmer existe a noção de que programar não é uma ciência exata. Não é produção, tampouco engenharia. Programar é uma atividade que requer &#8230; <a href="http://seiti.eti.br/blog/2009/programar-e-arte">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>O tema é recorrente.  Desde o monumental <a href="http://en.wikipedia.org/wiki/The_Art_of_Computer_Programming"><em>The Art of Computer Programming</em></a> ao, hmm&#8230;, pragmático  <a href="http://www.pragprog.com/titles/tpp/the-pragmatic-programmer"><em>The Pragmatic Programmer</em></a> existe a noção de que programar não é uma ciência exata. Não é produção, tampouco engenharia. Programar é uma atividade que requer criatividade, visão, trabalho e destreza. É <strong>arte</strong>.</p>
<p>Vem daí a dificuldade de se estabelecer prazos. De gerar metodologias. De ser produtivo, ter qualidade e criar soluções. Como apressar, controlar e gerenciar algo tão pessoal quanto a produção de código? Talvez tornando-o impessoal e automático. Mas não seria isto remover as características que diferenciam um software <strong>bom</strong> de um <strong>ótimo</strong>?</p>
<p>Pode-se criar arte em massa. Pode-se criar obra únicas. Pode-se apreciar ou não uma obra-prima.  Não é tão diferente no mundo do código fonte. Quem já não vislumbrou, modificando um programa qualquer, uma obra de arte <em>barroca</em>? Cheia de meandros, voltas, incertezas e becos sem saída. Um labirinto a provocar emoções: fúria, alegria,  raiva, medo, alívio (bom, este só quando o código compila e/ou passa nos testes). Estou divergindo&#8230;</p>
<p>E quem programa pode ser entendido como <em>um artesão.</em> Alguém que martela teclas para produzir, vez ou outra, um pouco de arte. E podemos encontrar,  procurando bastante,  entre estes artesãos, um verdadeiro <em>artista</em>.</p>
<h3><em>Why?</em></h3>
<p>É o caso de <a href="http://en.wikipedia.org/wiki/Why_the_lucky_stiff"><em>Why the Luck Stiff</em></a>, ou simplesmente _why. Seu trabalho mais conhecido é seu livro: <a href="http://seiti.eti.br/blog/2008/ruby-whys-poinant-guide-to-ruby">Why&#8217;s (poignant) Guide to Ruby</a>. Mesmo que você não programe, mesmo que você não entenda nem mesmo HTML, dê uma olhada.  O livro é excelente. Se parece com algo saído de uma viagem  de LSD, misturado com Alice no País das Maravilhas e lições de Ruby. E existe até uma trilha sonora para acompanhá-la!</p>
<p>Mas, onde encontro este livro? O site do _why saiu do ar. Assim como muitos outros projetos pertencentes a ele. Até a conta no twitter, @_why, sumiu. _why desapareceu. Ninguém sabe ninguém viu.</p>
<p style="text-align: center;"><a title="Where´s why? by Seiti Yamashiro, on Flickr" href="http://www.flickr.com/photos/seiti/3930444328/"><img src="http://farm4.static.flickr.com/3578/3930444328_30a945feac.jpg" alt="Where´s why?" width="284" height="480" /></a></p>
<p>É um feito notável para alguém que alcançou certa notoriedade online, e com uma presença forte na internet. Participou de palestras e eventos, mas sempre se identificando por seu pseudônimo.  Ainda existe o anonimato, afinal (há quem diga que <em>_why</em> apenas está dando um tempo e retornará como <em>_because</em>).</p>
<p>Mas dá para apreciar sua obra em alguns <a href="http://mislav.uniqpath.com/poignant-guide/">mirrors</a>.  E já tratei de guardar a <a href="http://mislav.uniqpath.com/poignant-guide/soundtrack/">trilha sonora</a> para ouvir enquanto programo. Quem sabe não tenho uma epifania (ou uma síncope, dependendo do código a editar). E tem até <a href="http://why.nomedojogo.com/">tradução para o português</a>, que até onde vi está ótima.</p>
<div class="wp-caption aligncenter" style="width: 570px"><img src="http://upload.wikimedia.org/wikipedia/en/0/04/Why%27s_foxes.png" alt="" width="560" height="162" /><p class="wp-caption-text">As raposas de _why</p></div>
<p>So long _why, and thanks for all the chunky bacon.
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2008/ruby-whys-poinant-guide-to-ruby" rel="bookmark" title="2 de julho de 2008">Ruby &#8211; Why&#8217;s (poinant) guide to ruby</a></li>
<li><a href="http://seiti.eti.br/blog/2009/fontpark-20" rel="bookmark" title="27 de janeiro de 2009">Fontpark 2.0</a></li>
<li><a href="http://seiti.eti.br/blog/2009/como-se-tornar-um-otimo-programador" rel="bookmark" title="12 de janeiro de 2009">Como se tornar um ótimo programador</a></li>
<li><a href="http://seiti.eti.br/blog/2009/desenvolvedor-web" rel="bookmark" title="10 de junho de 2009">Desenvolvedor Web</a></li>
</ul>
<p><!-- Similar Posts took 8.994 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2009/programar-e-arte/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ArcGIS Javascript, Dojo e o método require</title>
		<link>http://seiti.eti.br/blog/2009/arcgis-javascript-dojo-e-o-metodo-require</link>
		<comments>http://seiti.eti.br/blog/2009/arcgis-javascript-dojo-e-o-metodo-require#comments</comments>
		<pubDate>Wed, 16 Sep 2009 23:30:21 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[arcgis]]></category>
		<category><![CDATA[gis]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=777</guid>
		<description><![CDATA[Ando investigando a API Javascript ArcGIS. Esta API é escrita em cima do framework Dojo, que provê um monte de funções úteis, além de um biblioteca bacana de widgets. Tentando criar um código JS mais organizado, encontrei o método dojo.require, &#8230; <a href="http://seiti.eti.br/blog/2009/arcgis-javascript-dojo-e-o-metodo-require">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ando investigando a API <a href="http://resources.esri.com/arcgisserver/index.cfm?fa=JSAPIs">Javascript ArcGIS</a>. Esta API é escrita em cima do framework <a href="http://dojotoolkit.org/">Dojo</a>, que provê um monte de funções úteis, além de um biblioteca bacana de <em>widgets</em>.</p>
<p>Tentando criar um código <a href="http://en.wikipedia.org/wiki/Mission:_Impossible">JS mais organizado</a>, encontrei o método <a href="http://docs.dojocampus.org/dojo/require"><em>dojo.require</em></a>, que, em conjunto dos métodos <em>dojo.declare</em> e <em>dojo.provide</em>, devolvem um pouco de sanidade ao programandor.  Ele funciona da seguinte maneira.  Você inventa um namespace/pacote,  e depois associa um caminho à ele:</p>
<pre class="prettyprint">dojo.registerModulePath( "pacote", "http://localhost/scripts/")</pre>
<p>E depois pode incluir ou  importar pacotes assim:</p>
<pre class="prettyprint">dojo.require("pacote.MinhaClasse");</pre>
<p>A mágica é que o arquivo  <strong><em>http://localhost/scripts/MinhaClasse.js</em></strong> é  carregado automaticamente. Legal! Parecido com Java, C# e um monte de outras linguagens. Agora vou criar arquivos correspondentes às classes que criarei, e organizar a macarronada Javascript.</p>
<p><span style="text-decoration: line-through;">Mas não. A API Javascript ArcGIS, por alguma razão, procura pelo arquivo <strong><em>http://localhost/scripts/MinhaClasse.xd.js</em></strong> !!! De onde saiu este <strong>xd</strong>? E mesmo criando o arquivo que ele espera, seu conteúdo não é processado da forma correta.</span></p>
<p><span style="text-decoration: line-through;">Elaborando alguns testes eu susbtitui a referência:</span></p>
<blockquote class="prettyprint"><p><span style="text-decoration: line-through;">&lt;script type=&#8221;text/javascript&#8221; src=&#8221;http://serverapi.arcgisonline.com/jsapi/arcgis/?v=1.4&#8243;&gt;&lt;/script&gt;</span></p></blockquote>
<p><span style="text-decoration: line-through;">pela:</span></p>
<blockquote class="prettyprint"><p><span style="text-decoration: line-through;">&lt;script type=&#8221;text/javascript&#8221; src=&#8221;http://dojotoolkit.org/sites/all/modules/dojo/dtk_build/dojo/dojo.js&#8221;&gt;&lt;/script&gt;</span></p></blockquote>
<p><span style="text-decoration: line-through;">E funcionou ok. Parece que a versão do dojo entregue pela ESRI no ArcGIS não permite o uso do <em>dojo.require</em>. Para que isto seja possível, é necessário compilar o dojo de forma a permiti-lo carregar arquivos de domínios distintos, ou <a href="http://www.dojotoolkit.org/node/17"><em>cross domain</em></a>. Mas na API da ESRI não dá. Pena.</span></p>
<p>Encontrei como resolver o problema:</p>
<pre class="prettyprint">
        djConfig = {
            parseOnLoad: true,
            baseUrl: "./scripts",
            modulePaths: {
                "minhasClasses": "./minhasClasses",
                "meusDijits": "./BLA"
            },
           isDebug: true
        }
</pre>
<p>Isto me ensina a aprender direito antes de escrever! =)
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2010/carregando-bibliotecas-javascript-abertas" rel="bookmark" title="5 de fevereiro de 2010">Carregando bibliotecas Javascript abertas</a></li>
<li><a href="http://seiti.eti.br/blog/2010/funcoes-geoespaciais-do-ms-sql-server-2008" rel="bookmark" title="12 de março de 2010">Funções Geoespaciais do MS SQL Server 2008</a></li>
<li><a href="http://seiti.eti.br/blog/2010/cache-camadas-no-arcgis-server" rel="bookmark" title="8 de fevereiro de 2010">Cache e camadas no ArcGIS Server</a></li>
<li><a href="http://seiti.eti.br/blog/2008/sig-sistema-de-informacao-geografica" rel="bookmark" title="23 de abril de 2008">SIG &#8211; Sistema de Informação Geográfica</a></li>
</ul>
<p><!-- Similar Posts took 10.641 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2009/arcgis-javascript-dojo-e-o-metodo-require/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Odbc DataSource 32bits no Windows 7</title>
		<link>http://seiti.eti.br/blog/2009/odbc-datasource-32bits-no-windows-7</link>
		<comments>http://seiti.eti.br/blog/2009/odbc-datasource-32bits-no-windows-7#comments</comments>
		<pubDate>Mon, 31 Aug 2009 22:26:36 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[driver]]></category>
		<category><![CDATA[odbc]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=770</guid>
		<description><![CDATA[Ando efetuando uns testes com o Postgresql e o Virtual Box, ambos excelentes sistemas. No Virtual Box eu criei uma máquina virtual, nele instalando um Ubuntu Server 64 bits com o Postgresql &#8211; e configurando o postgresql.conf e pg_hba.conf como &#8230; <a href="http://seiti.eti.br/blog/2009/odbc-datasource-32bits-no-windows-7">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ando efetuando uns testes com o Postgresql e o Virtual Box, ambos excelentes sistemas. No Virtual Box eu criei uma máquina virtual, nele instalando um Ubuntu Server 64 bits com o Postgresql &#8211; e configurando o <em>postgresql.conf</em> e <em>pg_hba.conf</em> como sempre.</p>
<p>A partir de outra máquina virtual, rodando o Ubuntu Jaunty Desktop, consigo normalmente acessar o banco de dados no Ubuntu Server, então tudo ok. Ou quase tudo ok.</p>
<p>Para acessar o banco de dados postgresql a partir de meu sistema <strong>hospedeiro</strong> &#8211; ou seria <strong>anfitirião</strong>? <strong>estalajadeiro</strong>?, rodando o indefectível ( até o momento) Windows 7 tive de instalar os controladores ODBC (disponíves no <a href="http://www.postgresql.org/ftp/odbc/versions/msi/">ftp do Postgresql</a>) .</p>
<p>Depois de instalar, navego até o <em>Painel de Controle</em>, depois para  <em>Fontes de dados Odbc</em> e, CADÊ? Sumiu, ninguém viu. Só aparecem listados os controladores das fontes de dados do SQL Server. Muito estranho.</p>
<p>Mas eu já havia feito isto. Uma busca em <a href="http://www.google.com">minha memória</a> e<a href="http://razorsql.com/docs/odbc_setup.html"> me lembrei</a> que era um problema de versão do sistema. O controlador, ou <em>driver</em> , que instalei é de 32 bits. O sistema é de 64 bits. E o Windows não gosta de misturar alhos com bugalhos.</p>
<p>Para acessar finalmente o gerenciador de fontes de dados ODBC 32 bits é necessário executar este safado:</p>
<blockquote><p>C:\Windows\SysWOW64\odbcad32.exe</p></blockquote>
<p>Agora sim!
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2010/impressora-epson-tx600fw" rel="bookmark" title="15 de março de 2010">Impressora Epson TX600FW</a></li>
<li><a href="http://seiti.eti.br/blog/2007/recriando-o-show-desktop" rel="bookmark" title="11 de julho de 2007">Recriando o Show Desktop</a></li>
<li><a href="http://seiti.eti.br/blog/2009/nao-consegue-listar-os-databases-no-sql-management-studio" rel="bookmark" title="16 de junho de 2009">Não consegue listar os Databases no SQL Management Studio?</a></li>
<li><a href="http://seiti.eti.br/blog/2009/lerdeza-para-remover-arquivos-no-vista" rel="bookmark" title="24 de abril de 2009">Lerdeza para remover arquivos no Vista?</a></li>
</ul>
<p><!-- Similar Posts took 6.770 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2009/odbc-datasource-32bits-no-windows-7/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Upgrade no PostGIS</title>
		<link>http://seiti.eti.br/blog/2009/upgrade-no-postgis</link>
		<comments>http://seiti.eti.br/blog/2009/upgrade-no-postgis#comments</comments>
		<pubDate>Tue, 11 Aug 2009 22:48:35 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[gis]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=765</guid>
		<description><![CDATA[Algumas vezes é necessário um upgrade no banco de dados. E chegou a vez do PostgreSQL, para ir da versão 8.2 para a 8.3.  Aproveitando, fiz um upgrade do PostGIS 1.1.6 para a versão 1.4.  Surpreendentemente não ocorreram grandes problemas. &#8230; <a href="http://seiti.eti.br/blog/2009/upgrade-no-postgis">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Algumas vezes é necessário um upgrade no banco de dados. E chegou a vez do PostgreSQL, para ir da versão 8.2 para a 8.3.  Aproveitando, fiz um upgrade do PostGIS 1.1.6 para a versão 1.4.  Surpreendentemente não ocorreram grandes problemas. Quer dizer, não até eu migrar os dados.</p>
<p>O próprio PostGIS possui um <a href="http://postgis.refractions.net/docs/ch02.html#hard_upgrade">script para migração de dados</a>. Se trata de um script <em>Perl</em> que recebe um dump do PostgreSQL e mais alguns outros parâmetros, trata-os gerando um novo dump e depois finalmente faz o <em>restore</em> do dump no banco de dados.</p>
<h3>Problemas</h3>
<p>Parecia tudo ok, até eu tentar fazer um backup do novo banco:</p>
<blockquote><p>ERROR:  geometry contains non closed rings</p></blockquote>
<p>Será que os dados se corromperam durante a migração?</p>
<p>O PostGIS 1.4 é um pouco mais restritivo quanto aos dados que armazena. Um <em>multipolygon </em>ou <em>polygon</em>, por exemplo, só podem ser inseridos no sistema se estiverem bem formados, o que significa que devem ser polígonos <strong>fechados</strong> (hmm,  e existe &#8220;polígono aberto&#8221;?).</p>
<p>O problema é que a versão 1.1.6 é mais, digamos, liberal. Você consegue gravar &#8220;polígonos  abertos&#8221;, consegue fazer <em>SELECT</em>s e backups em cima deles. Apenas operações  que envolvam as formas geométricas podem dar problema.</p>
<p>E o processo de migração de dados não realiza nenhuma verificação de validade destas entidades.</p>
<p>Assim, os dados migrados para a nova versão continua com &#8220;polígonos abertos&#8221;,  impossibilitando, na versão 1.4,  até mesmo um simples <em>select</em> sobre os dados da tabela.</p>
<p>A solução foi encontrar os registros com este problema e removê-los da tabela através da seguinte consulta SQL:</p>
<pre style="prettyprint">DELETE
FROM &lt;nome_da_tabela&gt;
WHERE isvalid(coords) != 't'</pre>
<p>E se você possui muitas tabelas com o problema, boa sorte!
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2008/sig-sistema-de-informacao-geografica" rel="bookmark" title="23 de abril de 2008">SIG &#8211; Sistema de Informação Geográfica</a></li>
<li><a href="http://seiti.eti.br/blog/2009/arcsde-e-ms-sql-server-2008" rel="bookmark" title="23 de outubro de 2009">ArcSDE e MS SQL Server 2008</a></li>
<li><a href="http://seiti.eti.br/blog/2009/arcgis-javascript-dojo-e-o-metodo-require" rel="bookmark" title="16 de setembro de 2009">ArcGIS Javascript, Dojo e o método require</a></li>
<li><a href="http://seiti.eti.br/blog/2010/cache-camadas-no-arcgis-server" rel="bookmark" title="8 de fevereiro de 2010">Cache e camadas no ArcGIS Server</a></li>
</ul>
<p><!-- Similar Posts took 9.287 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2009/upgrade-no-postgis/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Problema rodando testes MbUnit no VS2008 Test Runner</title>
		<link>http://seiti.eti.br/blog/2009/problema-rodando-testes-mbunit-no-vs2008-test-runner</link>
		<comments>http://seiti.eti.br/blog/2009/problema-rodando-testes-mbunit-no-vs2008-test-runner#comments</comments>
		<pubDate>Mon, 03 Aug 2009 17:30:17 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[test]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=760</guid>
		<description><![CDATA[Importei um projeto para trabalhar em meu Visual Studio 2008. Ao tentar rodar os testes, que utilizam o framework MbUnit, fui contemplado com a seguinte mensagem: No tests were run because no tests are loaded or the selected tests are &#8230; <a href="http://seiti.eti.br/blog/2009/problema-rodando-testes-mbunit-no-vs2008-test-runner">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Importei um projeto para trabalhar em meu Visual Studio 2008. Ao tentar rodar os testes, que utilizam o framework MbUnit, fui contemplado com a seguinte mensagem:</p>
<blockquote><p>No tests were run because no tests are loaded or the selected tests are disabled</p></blockquote>
<p>O problema é que o projeto de testes é tratado como uma simples biblioteca de classes, embora seus métodos sejam decorados com atributos [Test] e similares.</p>
<p>E como fazer o VS2008 entender que o projeto em questão é de <strong>testes</strong>? É necessário abrir o arquivo <tt>.csproj</tt> correspondente ao projeto e incluir o seguinte:</p>
<pre>&lt;ProjectTypeGuids&gt;
{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
&lt;/ProjectTypeGuids&gt;</pre>
<p>Logo antes do primeiro <tt>&lt;/PropertyGroup&gt;</tt> do arquivo. O VS2008 verifica o tipo do projeto em questão através destes identificadores. E como encontrei estes números? Criei um projeto de testes MSTest pelo VS2008 e abri o .csproj.</p>
<p>E <a href="http://alexduggleby.com/2008/02/19/turning-a-class-library-project-into-a-mstest-project-or-using-mbunit-mstest-and-other-frameworks-in-one-project/#comment-1252">encontrei o significado </a> destes guids:</p>
<ul>
<li><tt>{3AC096D0-A1C2-E12C-1390-A8335801FDAB}</tt> identifica um <em>Test Project</em></li>
<li><tt>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</tt> identifica um <em>Windows Forms C# Project</em></li>
</ul>
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2009/compilando-seu-web-application-project-com-o-msbuild" rel="bookmark" title="6 de maio de 2009">Compilando seu Web Application Project com o MSBuild</a></li>
<li><a href="http://seiti.eti.br/blog/2010/erro-no-deploy-automatico-hudson-versus-msbuild" rel="bookmark" title="11 de maio de 2010">Erro no deploy automático: Hudson versus MSBuild</a></li>
<li><a href="http://seiti.eti.br/blog/2010/o-menu-asp-net-e-o-chrome-e-safari" rel="bookmark" title="11 de janeiro de 2010">O Menu Asp.NET e o Chrome (e Safari)</a></li>
<li><a href="http://seiti.eti.br/blog/2009/gerando-boletos-bancarios-em-aspnet-parte-i" rel="bookmark" title="13 de maio de 2009">Gerando boletos bancários em Asp.NET &#8211; Parte I</a></li>
</ul>
<p><!-- Similar Posts took 8.011 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2009/problema-rodando-testes-mbunit-no-vs2008-test-runner/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gerando boletos bancários em Asp.NET &#8211; Parte II</title>
		<link>http://seiti.eti.br/blog/2009/gerando-boletos-bancarios-em-aspnet-parte-ii</link>
		<comments>http://seiti.eti.br/blog/2009/gerando-boletos-bancarios-em-aspnet-parte-ii#comments</comments>
		<pubDate>Thu, 16 Jul 2009 18:58:21 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=617</guid>
		<description><![CDATA[Na Parte I vimos como emitir um boleto para impressão.  O que falta é populá-lo com dados que façam sentido. Vamos então populá-lo com dados relevantes. Em primeiro lugar é necessário que você tenha os dados armazenados em algum lugar, &#8230; <a href="http://seiti.eti.br/blog/2009/gerando-boletos-bancarios-em-aspnet-parte-ii">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Na <a href="http://seiti.eti.br/blog/2009/gerando-boletos-bancarios-em-aspnet-parte-i">Parte I</a> vimos como emitir um boleto para impressão.  O que falta é populá-lo com dados que façam sentido. Vamos então populá-lo com dados relevantes.</p>
<p>Em primeiro lugar é necessário que você tenha os dados armazenados em algum lugar, um banco de dados talvez. Mas vou presumir que seu código já trate dos dados e me ater à construção de duas partes fundamentais do boleto: a <em>linha digitável</em> e o <em>código de barras</em>.</p>
<p>Note que, embora alguns dígitos da <strong>linha digitável</strong> sigam um padrão, cada banco pode possuir regras próprias para gerá-la. Entre em contato com seu banco para ter essas informações.</p>
<p><span id="more-617"></span></p>
<h3>Linha digitável</h3>
<p>A linha digitável, lembrando novamente que estou seguindo as instruções do Itaú, possui 47 dígitos.</p>
<p>Abaixo segue a construção da linha, lembrando que DAC significa <em>dígito de auto-conferência</em>, ou simplesmente <strong>dígito verificador</strong>.</p>
<table border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td>AAABC.CCDDX</td>
<td>DDDDD.DEFFFY</td>
<td>FGGGG.GGHHHZ</td>
<td>K</td>
<td>UUUUVVVVVVVVVV</td>
</tr>
<tr>
<td>campo 1<br />
10 dígitos</td>
<td>campo 2<br />
11 dígitos</td>
<td>campo 3<br />
11 dígitos</td>
<td>4</td>
<td>campo 5<br />
14 dígitos</td>
</tr>
</tbody>
</table>
<p>Campo 1 (AAABC.CCDDX):</p>
<ul>
<li>AAA = código do banco &#8211; Itaú = 341;</li>
<li>B = código da moeda &#8211; Real = 9;</li>
<li>CCC = código da carteira de cobrança;</li>
<li>DD = dois primeiros dígitos do <em>Nosso Número</em>;</li>
<li>X = DAC  módulo 10 do campo 1;</li>
</ul>
<p>Campo 2 (DDDDD.DEFFFY):</p>
<ul>
<li>DDDDDD = restante do <em>Nosso Número;</em></li>
<li>E = DAC do grupo <em>agência/conta/carteira/nosso número</em>;</li>
<li>FFF = três primeiros números da agência;</li>
<li>Y = DAC módulo 10 do campo 2;</li>
</ul>
<p>Campo 3 (FGGGG.GGHHHZ):</p>
<ul>
<li>F = último número da agência;</li>
<li>GGGGGG = conta corrente + DAC;</li>
<li>HHH = zeros;</li>
<li>Z = DAC módulo 10 do campo 3;</li>
</ul>
<p>Campo 4 (K):</p>
<ul>
<li>K = DAC módulo 11 do código de barras (único DAC que vai para o código de barras);</li>
</ul>
<p>Campo 5 (UUUUVVVVVVVVVV):</p>
<ul>
<li>UUUU = fator de vencimento;</li>
<li>VVVVVVVVVV = valor do boleto, sem ponto e vírgula, ou zeros, no caso do valor ser preenchido pelo próprio sacado.</li>
</ul>
<p>O<em> fator de vencimento</em> contém 4 dígitos e é o número de dias desde 7 de outubro de 1997,  servindo para indicar a data de vencimento do boleto (teremos o bug do <span style="text-decoration: line-through;">milênio</span> 21 de fevereiro de 2025?).</p>
<p>Seu cálculo é bem simples, como podemos ver pelo método abaixo:</p>
<pre class="brush: csharp;">private int FatorVencimento(DateTime date)
{
    DateTime zeroDay = new DateTime(1997, 10, 7);
    return (date - zeroDay).Days;
}</pre>
<h3>DAC</h3>
<p>Analisando as regras anteriores, temos que a maior parte do trabalho consiste-se em concatenar strings e calcular DACs.</p>
<p>Para criar nossa Linha Digitável iremos dispor de dois algoritmos para calcular os DAC:s o módulo 10 e o módulo 11.</p>
<p>O cálculo do DAC módulo 10 é realizado da seguinte forma. Tome o campo a ter calculado o DAC. Multiplique cada algarismo do campo pela sequência de multiplicadores 2, 1, 2, 1, 2, 1&#8230;, posicionados<br />
da direita para a esquerda. Some os resultados, que chamarei de <em>N</em>.<br />
Calcule o módulo 10 de N &#8211; <strong>mod10(N)</strong> ou <strong>N%10</strong>.<br />
O DAC será <strong>10 &#8211; mod10(N)</strong>. Caso o DAC seja 10, considere-o como 0.</p>
<p>Segue abaixo um método para calcular o DAC módulo 10:</p>
<pre class="brush: csharp;">private int CalculaDacMod10(string campo)
{
    int soma = 0;
    int m;

    // caso exista um número par de algarismos, inicia a mult. por 1
    if ((campo.Length % 2) == 0)
        m = 1;
    else
        m = 2;
    foreach (char c in campo)
    {
        soma += Convert.ToInt32(c) * m;
        m = 3 - m; //regra aplicada: (x+y) - x = y; (x+y) - y = x
    }

    int dac = 10 - (soma % 10);

    if (dac == 10)
        return 0;

    return dac;
}</pre>
<p>O cálculo do DAC módulo 11 é bem semelhante.Ele depois será utilizado para compor o <strong>DAC do código de barras</strong>.</p>
<p>Tendo o trecho a ter o DAC calculado, tome seus algarismos e multiplique-os, iniciando-se da direita para a esquerda, pela sequência numérica de 2 a 9 ( 2, 3, 4, 5, 6,<br />
7, 8, 9, 2, 3, 4&#8230; e assim por diante). Some o resultado obtendo nosso <em>N.</em></p>
<p>Calcule agora o módulo 11 de <em>N</em> &#8211; <strong>mod11(N)</strong> ou <strong>N%11</strong>. O DAC será <strong>11 &#8211; mod11(N)</strong>. Caso o cálculo do DAC tenha dado 0, 10 ou 11, considere-o como 1.</p>
<p>O método abaixo faz o cálculo do DAC módulo 11:</p>
<pre class="brush: csharp;">private int CalculaDacMod11(string campo)
{
    int soma = 0;
    int m = 2;

    //Invertendo a string, para facilitar o trabalho com os multiplicadores
    char [] arr = campo.ToCharArray();
    Array.Reverse(arr);
    string reversed = new String(arr);

    foreach(char c in reversed)
    {
        soma += Convert.ToInt32(c) * m;
        m = (m + 1 &amp;gt; 9 ? 2 : m + 1);
    }

    int dac = 11 - (soma % 11);

    if (dac == 0 || dac == 10 || dac == 11)
        return 1;

    return dac;
}</pre>
<h3>Código de Barras</h3>
<p>O padrão de código de barras para os boletos no Brasil é o denominado <a href="(http://www.barcodeman.com/info/c2of5.php"><strong>2 de 5 intercalado</strong></a>, que pode ser resumido nas seguintes características:</p>
<ul>
<li>codifica apenas caracteres numéricos (<em>0-9</em>);</li>
<li>cada caractere é representado por 5 barras, dentre os quais 2 são mais longas;</li>
<li>codificação binária &#8211; largo é <strong>1</strong>, estreito é <strong><em>0</em></strong>;</li>
<li>os espaços também possuem signifcado, por isso o <em>intercalado</em></li>
</ul>
<p>Este código de barras serve apenas para representar nossa linha digitável, tranformado o que é uma seqüência de números em uma imagem. Existem muitos controles por aí que fazem isto, mas não encontrei nenhum gratuito para Asp.NET.</p>
<p>Neste  exemplo vou utilizar o <a href="http://barcodenet.net/">barcodenet.net</a>. Ele pode ser testado e é completamente funcional, a diferença é que, enquanto você não resgistrá-lo,  ele  criará uma linha escrito <em>barcodenet.net</em> (ou algo assim) logo acima  do código de barras.</p>
<p>Embora a linha digitável possua 47 dígitos, o número que será codificado em barras possui apenas 44. Por quê? Porque devemos nos livrar de três dos quatro DACs que constam nela. Assim o código de barra terá apenas um DAC.</p>
<p>Outra diferença importante é de que a ordem em que os campos se apresentam na linha digitável <strong>não é a mesma</strong> da apresentada pelo código de barras.</p>
<p>Segue como gerar então os dígitos que compõem o código de barras:</p>
<ul>
<li>3 dígitos do código do Banco (341);</li>
<li>1 dígito com o código da moeda (3);</li>
<li>1 dígito do DAC do Código de Barras;</li>
<li>4 dígitos do fator de vencimento;</li>
<li>10 dígitos do valor do tíitulo, desconsiderando qualquer sinal de pontuaçaõ;</li>
<li>3 dígitos da carteira;</li>
<li>9 dígitos do Nosso Número mais seu próprio DAC;</li>
<li>4 dígitos da agência;</li>
<li>6 dígitos da conta corrente, com seu próprio DAC;</li>
<li>3 dígitos não utilizados e composto por zeros (000).</li>
</ul>
<p>Depois de gerar os dígitos que compõem o código de barras, é questão de torná-lo em imagem utilizando o controle comentado anteriormente:</p>
<pre class="brush: csharp;">public byte[] CodigoBarras()
{
    BarcodeNETWeb barcode = new BarcodeNETWeb();
    barcode.BarcodeText = DigitosCodigoBarrasComDac();
    barcode.BarcodeType = BARCODE_TYPE.INT2OF5;

    return barcode.GetBarcodeBitmap(FILE_FORMAT.PNG);
}</pre>
<h3>Código</h3>
<p>Segue então a listagem do código fonte utilizado neste trabalho. Claro que há muito o que melhorar nele, mas isto fica como exercício. =)</p>
<p>Note que modifiquei a classe Dados do post anterior.</p>
<pre class="brush: csharp;">public class LinhaDigitavel
{
    public int Banco { get; private set; }
    public int Moeda { get {return 9; }}
    public string CarteiraCobranca { get; private set; }
    public string NossoNumero { get; private set; }
    public string Agencia { get; private set; }
    public string ContaCorrente { get; private set; }
    public DateTime Vencimento { get; private set; }
    public decimal Valor { get; private set; }

    public LinhaDigitavel(
        int banco,
        string carteira,
        string nossonumero,
        string agencia,
        string contacorrente,
        DateTime vencimento,
        decimal valor)
    {
        this.Banco = banco;
        this.CarteiraCobranca = carteira;
        this.NossoNumero = nossonumero;
        this.Agencia = agencia;
        this.ContaCorrente = contacorrente;
        this.Vencimento = vencimento;
        this.Valor = valor;
    }

    public LinhaDigitavel(Dados dados)
    {
        this.Banco = dados.Banco;
        this.CarteiraCobranca = dados.Carteira;
        this.NossoNumero = dados.NossoNumero;
        this.Agencia = dados.Agencia;
        this.ContaCorrente = dados.ContaCorrente;
        this.Vencimento = dados.DataVencimento;
        this.Valor = dados.ValorDocumento;
   } 

    public string FormatoParaImpressao()
    {
        return
            Campo1().Substring(0, 5) + &quot;.&quot; + Campo1().Substring(5) + &quot; &quot;
            + Campo2().Substring(0, 5) + &quot;.&quot; + Campo2().Substring(5) + &quot; &quot;
            + Campo3().Substring(0, 5) + &quot;.&quot; + Campo3().Substring(5) + &quot; &quot;
            + Campo4() + &quot; &quot;
            + Campo5();
    }

    public byte[] CodigoBarras()
    {
        BarcodeNETWeb barcode = new BarcodeNETWeb();
        barcode.BarcodeText = DigitosCodigoBarrasComDac();
        barcode.BarcodeType = BARCODE_TYPE.INT2OF5;

        return barcode.GetBarcodeBitmap(FILE_FORMAT.PNG);
    }

    private string Campo1()
    {
        string campo =
            this.Banco.ToString(&quot;000&quot;)
            + this.Moeda.ToString(&quot;0&quot;)
            + this.CarteiraCobranca.Trim()
            + this.NossoNumero.Split('-')[0].Substring(0, 2);

        if (campo.Length != 9) throw new Exception(&quot;Entrada inválida&quot;);

        return campo + CalculaDacMod10(campo).ToString(&quot;0&quot;);
    }

    private string Campo2()
    {
        string campo =
            this.NossoNumero.Split('-')[0].Substring(2, 6)
            + this.DacAgenciaContaCarteiraNossNumero().ToString(&quot;0&quot;)
            + this.Agencia.Substring(0, 3);

        if (campo.Length != 10) throw new Exception(&quot;Entrada inválida&quot;);

        return campo + CalculaDacMod10(campo).ToString(&quot;0&quot;);
    }

    private string Campo3()
    {
        string campo =
            this.Agencia.Substring(3, 1)
            + this.ContaCorrente.Split('-')[0] + this.ContaCorrente.Split('-')[1] //sinto falta de explode/implode
            + &quot;000&quot;;

        if (campo.Length != 10) throw new Exception(&quot;Entrada inválida&quot;);

        return campo + CalculaDacMod10(campo).ToString(&quot;0&quot;);
    }

    private string Campo4()
    {
        return DacCodigoBarras().ToString(&quot;0&quot;);
    }

    private string Campo5()
    {

        return
            this.FatorVencimento().ToString(&quot;0000&quot;)
            + FormataValor(this.Valor);
    }

    private string FormataValor(decimal valor)
    {
        string[] value = this.Valor.ToString(&quot;00000000.00&quot;, System.Globalization.CultureInfo.InvariantCulture).Split('.');
        return value[0] + value[1];
    }

    private int DacAgenciaContaCarteiraNossNumero()
    {
        string termo =
            this.Agencia
            + this.ContaCorrente.Split('-')[0]
            + this.CarteiraCobranca
            + this.NossoNumero.Split('-')[0];

        if (termo.Length != 20) throw new Exception(&quot;Entrada inválida&quot;);

        return CalculaDacMod10(termo);
    }

    private int DacCodigoBarras()
    {
        return CalculaDacMod11(DigitosCodigoBarrasSemDac());
    }

    private string DigitosCodigoBarrasSemDac()
    {

        string termo =
            this.Banco.ToString(&quot;000&quot;)
            + this.Moeda.ToString(&quot;0&quot;)
            + this.FatorVencimento().ToString(&quot;0000&quot;)
            + this.Valor.ToString(&quot;0000000000&quot;)
            + this.CarteiraCobranca
            + this.NossoNumero.Split('-')[0] + this.NossoNumero.Split('-')[1]
            + this.Agencia
            + this.ContaCorrente.Split('-')[0] + this.ContaCorrente.Split('-')[1] //sinto falta de explode/implode
            + &quot;000&quot;;

        return termo;
    }

    private string DigitosCodigoBarrasComDac()
    {
        string termo = DigitosCodigoBarrasSemDac();
        return termo.Substring(0, 4) + DacCodigoBarras().ToString(&quot;0&quot;) + termo.Substring(4);
    }

    private int FatorVencimento()
    {
        DateTime zeroDay = new DateTime(1997, 10, 7);
        return (this.Vencimento - zeroDay).Days;
    }

    ///
    /// DAC móulo 10
    /// Exemplo:
    /// Considerando-se a seguinte representação numérica do código de barras:
    /// 34191.1012? 34567.88005? 71234.57000? 6 16670000012345
    /// Temos:
    /// a) Multiplicando a sequência dos campos pelo módulo 10:
    ///  Campo 1 341911012 Campo 2 3456788005 Campo 3 7123457000
    ///        X 212121212       X 1212121212       X 1212121212
    ///  Observação: Os campos 4 e 5 não tem DAC
    /// b) Some, individualmente, os algarismos dos resultados do produtos:
    ///  Campo 1 : 6 + 4 + 2 + 9 + 2 + 1 + 0 + 1 + 4 = 29
    ///  Campo 2 : 3 + 8 + 5 + 1 + 2 + 7 + 1 + 6 + 8 + 0 + 0 + 1 + 0 = 42
    ///  Campo 3 : 7 + 2 + 2 + 6 + 4 + 1 + 0 + 7 + 0 + 0 + 0 = 29
    /// c) Divida o total encontrado por 10, a fim de determinar o resto da divisão:
    ///  Campo 1 : 29 / 10 = 2, resto 9
    ///  Campo 2 : 42 / 10 = 4, resto 2
    ///  Campo 3 : 29 / 10 = 2, resto 9
    /// d) Calculando o DAC:
    ///  Campo 1 : DAC = 10 - 9 : DAC = 1
    ///  Campo 2 : DAC = 10 - 2 : DAC = 8
    ///  Campo 3 : DAC = 10 - 9 : DAC = 1
    /// Portanto, a sequência correta da linha digitável será:
    ///  34191.10121 34567.880058 71234.570001 6 16670000012345
    ///
    ///
&lt;span&gt; &lt;/span&gt;
    ///
    private int CalculaDacMod10(string campo)
    {
        int soma = 0;
        int m;

        // caso exista um número par de algarismos, inicia a mult. por 1
        if ((campo.Length % 2) == 0)
            m = 1;
        else
            m = 2;
        foreach (char c in campo)
        {
            soma += Convert.ToInt32(c) * m;
            m = 3 - m; //regra aplicada: (x+y) - x = y; (x+y) - y = x
        }

        int dac = 10 - (soma % 10);

        if (dac == 10)
            return 0;

        return dac;
    }

    ///
    /// Considerando o seguinte conteúdo do Código de Barras:
    ///  3419?1667000001234511012345678800571423457000
    /// onde:
    ///  341 = Código do Banco
    ///  9 = Código da Moeda
    ///  ? = DAC do Código de Barras
    ///  1667 Fator de Vencimento (01/05/2002)
    ///  0000012345 = Valor do Título (123,45)
    ///  110123456788 = Carteira/Nosso Número/DAC (110/12345678-8)
    ///  0057123457 = Agência/Conta Corrente/DAC (0057/12345-7)
    ///  000 = Posições Livres (zeros)
    ///  Temos:
    ///   a) Multiplica-se a sequência do código de barras pelo módulo 11:
    ///      3419166700000123451101234567880057123457000
    ///    X 4329876543298765432987654329876543298765432
    /// b) Soma-se o resultado dos produtos obtidos no item “a” acima:
    ///   12 + 12 + 2 + 81 + 8 + 42 + 36 + 35 + 0 + 0 + 0 + 0 + 0 + 7 + 12 + 15 + 16 + 15 + 2 +
    ///   9 + 0 + 7 + 12 + 15 + 16 + 15 + 12 + 63 + 64 + 56 + 0 + 0 + 20 + 21 + 2 + 18 + 24 +
    ///   28 + 30 + 35 + 0 + 0 + 0 = 742
    /// c) Determina-se o resto da Divisão:
    ///   742 / 11 = 67, resto 5
    /// d) Calcula-se o DAC:
    ///   DAC = 11 – 5  então  DAC = 6
    ///   Portanto, a sequência correta do código de barras será:
    ///   34196166700000123451101234567880057123457000
    ///       ^---DAC
    ///
    ///

    ///
    private int CalculaDacMod11(string campo)
    {
        int soma = 0;
        int m = 2;

        //Invertendo a string, para facilitar o trabalho com os multiplicadores
        char [] arr = campo.ToCharArray();
        Array.Reverse(arr);
        string reversed = new String(arr);

        foreach(char c in reversed)
        {
            soma += Convert.ToInt32(c) * m;
            m = (m + 1 &amp;gt; 9 ? 2 : m + 1);
        }

        int dac = 11 - (soma % 11);

        if (dac == 0 || dac == 10 || dac == 11)
            return 1;

        return dac;
    }
}</pre>
<pre class="brush: csharp;">public class Dados
{
    public DateTime DataDocumento { get; set; }
    public DateTime DataVencimento { get; set; }
    public DateTime DataProcessamento { get; set; }

    public string Cedente { get; set; }
    public string SacadoResumido { get; set; }
    public string SacadoCompleto { get; set; }

    public int Banco { get; set; }
    public string Agencia { get; set; }
    public string ContaCorrente { get; set; }
    public string CodigoCedente { get; set; }

    public int NumeroDocumento { get; set; }
    public string EspecieDocumento { get; set; }
    public string Aceite { get; set; }
    public string NossoNumero { get; set; }
    public string Carteira { get; set; }

    public string Instrucoes { get; set; }

    public int Quantidade { get; set; }
    public decimal Valor { get; set; }
    public decimal ValorDocumento { get; set; }

    public string CodigoBaixa { get; set; }
    public byte[] CodigoBarra
    {
        get
        {
            LinhaDigitavel linha = new LinhaDigitavel(this);
            return linha.CodigoBarras();
        }
    }
    public string LinhaDigitavel
    {
        get
        {
            LinhaDigitavel linha = new LinhaDigitavel(this);
            return linha.FormatoParaImpressao();
        }
    }
}</pre>
<p>Um exemplo de uso do gerador de boletos:</p>
<pre class="brush: csharp;">protected void btnGeraBoleto_OnClick(object sender, EventArgs e)
{
    Boleto boleto = new Boleto(Portal.Controles.Boleto.Banco.ITAU, Server);
    List
 dados = new List
();

    dados.Add(
        new Portal.Controles.Boleto.Dados()
        {
            Aceite = &quot;N&quot;,
            Agencia = &quot;1234&quot;,
            Banco = 341,
            Carteira = &quot;109&quot;,
            Cedente = &quot;Indústria ACME&quot;,
            CodigoBaixa = &quot;109/12345678-9&quot;,
            CodigoCedente = &quot;12345-6&quot;,
            ContaCorrente = &quot;12345-6&quot;,
            DataDocumento = DateTime.Now,
            DataProcessamento = DateTime.Now,
            DataVencimento = new DateTime(2009, 4, 5),
            EspecieDocumento = &quot;DM&quot;,
            Instrucoes =
@&quot;Não receber após o vencimento&quot;,
            NossoNumero = &quot;12345678-9&quot;,
            NumeroDocumento = 0000000012,
            Quantidade = 0,
            SacadoCompleto =
@&quot;Padoca do Zé - LTDA                  CNPJ - 12.345.678/0001-23
Rua das Casas, 123
01234-123        Vl do Bairro          Sao Paulo          SP&quot;,
            SacadoResumido = &quot;Padoca do Zé - LTDA&quot;,
            Valor = 0,
            ValorDocumento = 2637.00m
        });

    boleto.Baixa(Response, dados);
}</pre>
<h3>Fechando</h3>
<p>Embora existam outras opções, como cartões de crédito e pagamento direto online, o boleto ainda é utilizado devido à familiaridade e facilidade de pagamento por parte do comprador. Por isso temos de saber gerá-lo em nossos sistemas, mesmo que utilizemos soluções prontas.</p>
<p>Vimos que gerar um boleto na plataforma .Net é algo simples, composto por uma guia impressa, alguma lógica para a geração da linha digitável e uma ferramenta de terceiros para a criação do código de barras. A parte mais difícil fica no sistema subjacente, não abordada, onde entra o retorno do pagamento do boleto e finalmente na remessa da mercadoria. Mas isto fica para uma próxima.
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2009/gerando-boletos-bancarios-em-aspnet-parte-i" rel="bookmark" title="13 de maio de 2009">Gerando boletos bancários em Asp.NET &#8211; Parte I</a></li>
<li><a href="http://seiti.eti.br/blog/2009/ligando-um-controle-a-um-enum" rel="bookmark" title="15 de maio de 2009">Ligando um controle à um Enum</a></li>
<li><a href="http://seiti.eti.br/blog/2009/httppostedfile-ie-versus-firefox" rel="bookmark" title="17 de maio de 2009">HttpPostedFile: IE versus Firefox</a></li>
<li><a href="http://seiti.eti.br/blog/2009/conseguindo-a-url-completa-de-uma-pagina" rel="bookmark" title="19 de maio de 2009">Conseguindo a URL completa de uma página</a></li>
</ul>
<p><!-- Similar Posts took 12.450 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2009/gerando-boletos-bancarios-em-aspnet-parte-ii/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Embarcando código JavaScript</title>
		<link>http://seiti.eti.br/blog/2009/embarcando-codigo-javascript</link>
		<comments>http://seiti.eti.br/blog/2009/embarcando-codigo-javascript#comments</comments>
		<pubDate>Wed, 24 Jun 2009 21:23:24 +0000</pubDate>
		<dc:creator>seiti</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[asp.net]]></category>

		<guid isPermaLink="false">http://seiti.eti.br/blog/?p=687</guid>
		<description><![CDATA[Ao se criar um Server Control em Asp.NET, e queremos que ele contenha lógica a ser executada no cliente recorremos ao Javascript. Uma das maneiras de se incluir código Javascript no controle é este: protected override void OnPreRender(EventArgs e) { &#8230; <a href="http://seiti.eti.br/blog/2009/embarcando-codigo-javascript">Continue lendo <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Ao se criar um Server Control em Asp.NET, e queremos que ele contenha lógica a ser executada no cliente recorremos ao Javascript.</p>
<p>Uma das maneiras de se incluir código Javascript no controle é este:</p>
<pre class="prettyprint">protected override void OnPreRender(EventArgs e)
{
    base.OnPreRender(e);
    if (!Page.ClientScript.IsClientScriptBlockRegistered("algumid"))
    {
        string script = @"
function MinhaFuncaoJS()
{
    ...
    ...
    ...
}
...
...
...
function OutraFuncaoJS()
{
    ...
    ...
    ...
}
";
        Page.ClientScript.RegisterClientScriptBlock(
            this.GetType(),
            "algumid",
            script,
            true);
    }
}</pre>
<p>O que não é muito bom por alguns motivos, entre outros:</p>
<ul>
<li>se torna difícil reutilizar código Javascript;</li>
<li>deve-se tomar cuidado ao incluir mais de um controle na página, pois acaba-se incluindo o mesmo código Javascript mais de uma vez na página;</li>
<li>é mais fácil cometer equívocos no código Javascript.</li>
</ul>
<p>A maneira de se contornar isto é <strong>embarcando</strong> o código Javascript na aplicação &#8211; ou <em>embedding the script resource</em>.</p>
<p>Para tanto você apenas cria o arquivo contendo o script, por exemplo <tt>MeuProjeto/minhasfuncoes.js</tt>, o inclui no projeto e, através de suas propriedades, configura o item <strong>Build Action</strong> como <em>Embedded Resource</em>.</p>
<div class="wp-caption aligncenter" style="width: 264px"><a title="Propriedade para embarcar o arquivo by Seiti Yamashiro, on Flickr" href="http://www.flickr.com/photos/seiti/4619331459/"><img title="Embarcando arquivo" src="http://farm5.static.flickr.com/4042/4619331459_3803129779.jpg" alt="Propriedade para embarcar o arquivo" width="254" height="335" /></a><p class="wp-caption-text">Modifique esta propriedade para Embedded</p></div>
<p style="text-align: center;">
<p>Isto inclui o script na DLL gerada na compilação. Para acessá-lo é preciso registrá-lo no <tt>AssemblyInfo.cs</tt>:</p>
<pre class="prettyprint">[assembly: WebResource("MeuProjeto.minhasfuncoes.js", "text/javascript")]
</pre>
<p>E depois em cada controle que irá utilizar o script:</p>
<pre class="prettyprint">protected override void OnPreRender(EventArgs e)
{
    Page.ClientScript.RegisterClientScriptResource(
        typeof(GeoImage),
        "MeuProjeto.minhasfuncoes.js");
    base.OnPreRender(e);
}
</pre>
<p>E pronto! O sistema irá incluir o script em sua página através de um handler <strong>WebResource.axd</strong>.
<p><strong>Posts relacionados</strong>
<ul class="similar-posts">
<li><a href="http://seiti.eti.br/blog/2008/framework-de-testes-funcionais-nexuslight" rel="bookmark" title="26 de setembro de 2008">Framework de testes funcionais NexusLight</a></li>
<li><a href="http://seiti.eti.br/blog/2008/datasource-parameters-falta-um-propertyparameter" rel="bookmark" title="22 de setembro de 2008">DataSource Parameters: falta um PropertyParameter!</a></li>
<li><a href="http://seiti.eti.br/blog/2009/ligando-um-controle-a-um-enum" rel="bookmark" title="15 de maio de 2009">Ligando um controle à um Enum</a></li>
<li><a href="http://seiti.eti.br/blog/2007/estendendo-o-boundfield" rel="bookmark" title="13 de novembro de 2007">Estendendo o BoundField</a></li>
</ul>
<p><!-- Similar Posts took 8.084 ms --></p>
]]></content:encoded>
			<wfw:commentRss>http://seiti.eti.br/blog/2009/embarcando-codigo-javascript/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
