luni, 27 februarie 2012

Linq To Objects Extension: Full Outer Join

I need a report which shows a comparison of the sales of each service with the previous year. Some services might be new and they don't appear in the previous year, others might be put off and so there are no sales for them in the current year. There can be services sold in both periods.


So I need a full outer join:

public static IEnumerable<TResult> FullOuterJoin<TOuter, TInner, TKey, TResult>
(this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector)
{
// left side
foreach (var current in outer)
{
if (!inner.Select(i => innerKeySelector(i)).Contains(outerKeySelector(current)))
yield return resultSelector(current, default(TInner));
}
// middle side
var innerJoin = outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector);
foreach (var current in innerJoin)
yield return current;
//right side
foreach (var current in inner)
{
if (!outer.Select(i => outerKeySelector(i)).Contains(innerKeySelector(current)))
yield return resultSelector(default(TOuter), current);
}
yield break;
}


public static IEnumerable<TResult> FullOuterJoin<TOuter, TInner, TKey, TResult>
(this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector,
IEqualityComparer<TKey> comparer)
{
foreach (var current in outer)
{
if (!inner.Select(i => innerKeySelector(i)).Contains(outerKeySelector(current), comparer))
yield return resultSelector(current, default(TInner));
}

var innerJoin = outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
foreach (var current in innerJoin)
yield return current;

foreach (var current in inner)
{
if (!outer.Select(i => outerKeySelector(i)).Contains(innerKeySelector(current), comparer))
yield return resultSelector(default(TOuter), current);
}
yield break;
}


An a sample:


var lastYearServices = new [] {
new {
Year = 2009,
Services = new []{ new { Service = "A", Amount = 2009200m },
new { Service = "B", Amount = 2009100m }}
},
new {
Year = 2010,
Services = new []{ new { Service = "X", Amount = 20102000m }}
},
new {
Year = 2011,
Services = new []{ new { Service = "AA", Amount = 2011200m }}
}
};

var currentYearServices = new [] {
new {
Year = 2010,
Services = new []{ new { Service = "B", Amount = 2010200m },
new { Service = "C", Amount = 2010100m }}
},
new {
Year = 2011,
Services = new []{ new { Service = "X", Amount = 2011200m }}
},
new {
Year = 2012,
Services = new []{ new { Service = "AA", Amount = 2012200m },
new { Service = "BB", Amount = 2012100m }}
}
};
var query = from l in lastYearServices
join c in currentYearServices on l.Year + 1 equals c.Year
select new {
Year = c.Year,
Services = l.Services.FullOuterJoin(c.Services, ls => ls.Service, cs => cs.Service, (ls, cs) => new {
LastYearAmount = ls != null ? ls.Amount : default(decimal?),
CurrentYearAmount = cs != null ? cs.Amount : default(decimal?),
Sevice = ls != null ? ls.Service : cs.Service
})
};
query.Dump();


vineri, 24 februarie 2012

SelectMany - projecting the index of the result

There are 4 overloads of the SelectMany method. Two of them project the index of each source element, for example:

string[] sentenceSequences = new string[] {"The quick brown", "fox jumped over","the lazy dog."};
sentenceSequences.SelectMany(
// index - the position of the sequence in the sentenceSequences array
(sequence, index) =>
// check if index is on odd position and if so call ToUpper()
// ... put the sequence in other array, as the result
index % 2 == 0 ? new [] {sequence.ToUpper()} : new [] { sequence }
)
.Dump();


But there is no overload for projecting the index of the result also (the index of the element in the result sequence). So here an implementation of it:


public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, int, TResult> resultSelector)
{
int collectionSelectorIndex = -1;
foreach (TSource sourceCurent in source)
{
collectionSelectorIndex++;
int resultSectorIndex = -1;
foreach (TCollection resultCurrent in collectionSelector(sourceCurent, collectionSelectorIndex))
{
resultSectorIndex++;
yield return resultSelector(sourceCurent, resultCurrent, resultSectorIndex);
}
}
yield break;
}

public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, int, TResult> resultSelector)
{
foreach (TSource sourceCurent in source)
{
int resultSectorIndex = -1;
foreach (TCollection resultCurrent in collectionSelector(sourceCurent))
{
resultSectorIndex++;
yield return resultSelector(sourceCurent, resultCurrent, resultSectorIndex);
}
}
yield break;
}


Some usage example:


sentenceSequences.SelectMany(
sequence => sequence.Split(' '),
(sequence, word, index) => new {sequence, word, index}
).SelectMany(
word => word.word.ToCharArray(),
(word, chr, index) => new {word.sequence, word.word, wordindex = word.index, @char = chr, charindex = index}
)
.Dump();

sentence word wordindex char charindex
The quick brown The 0 T 0
The quick brown The 0 h 1
The quick brown The 0 e 2
The quick brown quick 1 q 0
The quick brown quick 1 u 1
The quick brown quick 1 i 2
The quick brown quick 1 c 3
The quick brown quick 1 k 4
The quick brown brown 2 b 0
The quick brown brown 2 r 1
The quick brown brown 2 o 2
The quick brown brown 2 w 3
The quick brown brown 2 n 4
fox jumped over fox 0 f 0
fox jumped over fox 0 o 1
fox jumped over fox 0 x 2
fox jumped over jumped 1 j 0
fox jumped over jumped 1 u 1
fox jumped over jumped 1 m 2
fox jumped over jumped 1 p 3
fox jumped over jumped 1 e 4
fox jumped over jumped 1 d 5
fox jumped over over 2 o 0
fox jumped over over 2 v 1
fox jumped over over 2 e 2
fox jumped over over 2 r 3
the lazy dog. the 0 t 0
the lazy dog. the 0 h 1
the lazy dog. the 0 e 2
the lazy dog. lazy 1 l 0
the lazy dog. lazy 1 a 1
the lazy dog. lazy 1 z 2
the lazy dog. lazy 1 y 3
the lazy dog. dog. 2 d 0
the lazy dog. dog. 2 o 1
the lazy dog. dog. 2 g 2
the lazy dog. dog. 2 . 3


Now a more nicer projection:


sentenceSequences.SelectMany(
sequence => sequence.Split(' '),
(sequence, word, index) => new {sequence, word, index}
).SelectMany(
word => word.word.ToCharArray(),
(word, chr, index) => new {
// show the sequence only when the word and the char are the first line in their sequences
sequence = word.index == 0 && index == 0 ? word.sequence : null,
// show the word only when the projected char is the first one in its sequence
word = index == 0 ? word.word : null,
@char = chr,
}
).Dump()



sequence word char
The quick brown The T
h
e
quick q
u
i
c
k
brown b
r
o
w
n
fox jumped over fox f
o
x
jumped j
u
m
p
e
d
over o
v
e
r
the lazy dog. the t
h
e
lazy l
a
z
y
dog. d
o
g
.


This might be a good solution when I need to flatten a list of nested objects with some kind large depth (Customers -> Orders -> OrderItems -> OrderItemsHistory -> Updaters ). Flattening this structure means most of the properties get repeating themselves and I end up to use either the objects themselves to create a report with a tree of repeaters or to manipulate a single repeater and decide when to show a property or not.


The last example show how easy is to "hide" the flattened properties when the results selector of the SelectMany projects the index of the result item also.

vineri, 23 decembrie 2011

TakeFive - what an extension


public static class LinqExtensions
{
public public static IQueryable<T> TakeFive(this IQueryable<T> query)
{
return query.Take(5);
}
}

vineri, 25 noiembrie 2011

Extract currency values from text with T-SQL


CREATE FUNCTION dbo.fnGetAmounts(@str nvarchar(max))
RETURNS TABLE
AS
RETURN
(
-- generate all possible starting positions ( 1 to len(@str))
WITH StartingPositions AS
(
SELECT 1 AS Position
UNION ALL
SELECT Position+1
FROM StartingPositions
WHERE Position <= LEN(@str)
)
-- generate all possible lengths
, Lengths AS
(
SELECT 1 AS [Length]
UNION ALL
SELECT [Length]+1
FROM Lengths
WHERE [Length] <= 15
)
-- a Cartesian product between StartingPositions and Lengths
-- if the substring is numeric then get it
,PossibleCombinations AS
(

SELECT CASE
WHEN ISNUMERIC(substring(@str,sp.Position,l.Length)) = 1
THEN substring(@str,sp.Position,l.Length)
ELSE null END as Number
,sp.Position
,l.Length
FROM StartingPositions sp, Lengths l
WHERE sp.Position <= LEN(@str)
)
-- get only the numbers that start with Dollar Sign,
-- group by starting position and take the maximum value
-- (ie, from $, $2, $20, $200 etc)
SELECT MAX(convert(money, Number)) as Amount
FROM PossibleCombinations
WHERE Number like '$%'
GROUP BY Position
)

GO

declare @str nvarchar(max) = 'Used knife set for sale $200.00 or best offer. $20,000.35, $20000.3598,
$4,500 Persian rug for sale.
Today only, $100 rebate.
Five items for sale: $20 Motorola phone car charger, $150 PS2, $50.00 3 foot high shelf.
'

SELECT *
FROM dbo.fnGetAmounts(@str)
OPTION(MAXRECURSION 32767)

miercuri, 2 noiembrie 2011

The <link> saga on ASP .Net

Indeed, there is a saga. Since from the very beginning of my ASP .Net experiences I had to deal with the "CSS problem". This problem occurs when the referenced CSS is not loaded, because the relative path is not given right.

We place in the Master Page all the common html used in the website, including the links to the CSS files. Pages might be placed in different nested folders and because of this, the link to the CSS file needs to be adjusted with the relative prefixes. Since the link is placed in the Master Page and it is not known in advantage the website structure, the solution should solve the problem of how is the right prefix added to the CSS link.

HTML introduced Relative Uniform Resource Locators ( see [Page 11]) which actually solves this problem. Instead of writing the absolute paths (ie. http://www.mysite.com/public/main.css ), it suffices to use the relative paths, like public/main.css. That RFC explains the algorithm of how the prefixes ( /, ./, ../, ../../ so on) are going to be solved.

ASP .Net introduced the notion of the Virtual Directory and Application. For example www.mysite.com/admin might be an application different than the one on www.mysite.com, each with their own purposes and resources. The tilde "~" prefix has been added by ASP .Net to add an extra level of the relativity: to be "relative" to an application.
1. /public/main.css - it is translated as http://www.mysite.com/public/main.css no matter the place where it is referenced (ie from the root application or from the admin application)
2. ~/public/main.css - it is translated as http://www.mysite.com/public/main.css if the calling page is from the root application and http://www.mysite.com/admin/public/main.css if the calling page is from admin application.

Before going to the CSS problem, a small notice about the <head> element. If the runat="server" is specified then it is transformed in a server control. This means the generated code to build the page will contain a code snippet to create an instance of HtmlHead class. If runat="server" is not specified, the generated code will simple contain instructions for the writer to write the text found from (and including) <head> to the next server control or one of the instructions <%= ... %>, <%# ... %>, <%: ... %> or <%#: ... %> . It is important to know this, because if the head is a server control, then the links will be its child controls otherwise simply text passed to the writer.

Now back to the CSS problem, with the following structure I will try to give some explanations.




<head>
<link href='/public/main.css' type='text/css'/>
</head>

ASP .Net it passes this text to the writer (because head is not a server control). Every page will have the relative CSS translated to the following absolute path www.mysite.com/public/main.css. When the master page is located in the admin application and uses the same scheme it won't work as expected. The root is still http://www.mysite.com/ and not http://www.mysite.com/admin/. Here comes the ResolveUrl method.

<head>
<link href='<%= ResolveUrl("~/public/main.css")%>' type="text/css" />
</head>

Again, the text is passed to the writer until <%= instruction. Then the ResolveUrl is evaluated and its result is passed to writer. The output of this method is /admin/public/main.css because the tilde prefix says that it needs to take the application as the root of the page and not http://www.mysite.com.

What happens when head becomes a server control? As I said, ASP .Net won't pass the text to writer, it will auto-generate code for building an HtmlHead. The text inside the html tag it is parsed too and based on the results either it will pass text to the writer, either it will generate code to build HtmlTitle, HtmlMeta and HtmlLink instances. So if it finds <link href="/public/main.css" type="text/css" /> then it generates the following instructions:

@__ctrl = new global::System.Web.UI.HtmlControls.HtmlLink();
@__ctrl.Href = "/public/main.css";
((System.Web.UI.IAttributeAccessor)(@__ctrl)).SetAttribute("type", "text/css");

Now, it makes sense to use tilde (~) here, if it is needed. Also there is no reason to add runat="server" to the link, ASP .Net ignores it. I noticed that the output is different than ResolveUrl method, because ResolveUrl it uses the application name (admin in this case) and the HtmlLink control it renders the relative prefixes in such way the application name is avoided (public/main.css or ../public/main.css or ../../ so on).

Can the ResolveUrl method to be used with link and the html server control? Yes, but we need to trick ASP .Net parser. Let't try it first as "the normal" way, like this:

<head runat="server">
<link href='<%= ResolveUrl("~/public/main.css") %>' type="text/css" />
</head>

Unfortunately this will output some giberish:

<head id="Head1"><link href="&lt;%= ResolveUrl(&quot;~/public/main.css&quot;) %>" type="text/css" />
</head>

And the explanation is: ASP .Net it "sees" the instruction <%= ResolveUrl("~/public/main.css") %> as a plain text and it assigns it to the href attribute.

@__ctrl = new global::System.Web.UI.HtmlControls.HtmlLink();
@__ctrl.Href = "<%= ResolveUrl(\"~/public/main.css\") %>";
((System.Web.UI.IAttributeAccessor)(@__ctrl)).SetAttribute("type", "text/css");

By tricking the parser it means confusing it that link is not a text for HtmlLink.


<head runat="server">
<link <%= "href='" + ResolveUrl("~/public/main.css") + "'" %> type="text/css" />
</head>

What's the best practice? I believe the answer is, as always, it depends.
If the relative point it is the site itself than the / prefix ( it means start from the root of the website) it suffices and it doesn't matter if head is a server control or not ( and it shouldn't).
If the resource is relative to an application and the head is not a server control there is no way than using ResolveUrl method combined with tilde (~), but if the head is a server control there is no need to use ResolveUrl method, because the link is "transfomed" into a HtmlLink control and its Href property is assigned with the href value. If it is really needed to use ResolveUrl method ( or any other ?!, actually to use a <%= instruction inside the link element ), then the ASP .Net parser needs to be tricked.

vineri, 28 octombrie 2011

Generate class from a LINQ projection


using System;
using System.Linq;
using Microsoft.CSharp;
using System.CodeDom;

public static class QueryExtensions
{
public static string GetClassDefinition<T>(this IQueryable<T> query, string className)
{
var type = typeof(T);
var sb = new StringBuilder();
sb.AppendLine(string.Format("public class {0}", className));
sb.AppendLine("{");
using (var provider = new CSharpCodeProvider())
{
foreach ( var prop in type.GetProperties())
{
var typeRef = new CodeTypeReference(prop.PropertyType);
var propertyTypeName = provider.GetTypeOutput(typeRef);
if ( !propertyTypeName.StartsWith("<>"))
{
propertyTypeName = propertyTypeName.Replace("System.Nullable<", String.Empty)
.Replace(">","?")
.Replace("System.", String.Empty);
sb.AppendLine(string.Format("\tpublic {0} {1} {{get; set;}}", propertyTypeName, prop.Name));
}
}
}
sb.AppendLine("}");
return sb.ToString();
}
}


The reason of this snippet is because I was working to the following query which projects kind many properties and I want to reuse the results, so I needed to write a concrete class. Usually I build and test the queries with LINQPad so here follows a capture of my original query.



Creating a class with a bunch of properties is not the happiest moment, so I decided to generate it. The class looks like:

public class OrderItemDetails
{
public int order_item_id {get; set;}
public int order_id {get; set;}
public string session_id {get; set;}
public string root_plu {get; set;}
public string full_plu {get; set;}
public int? product_id {get; set;}
public int stock_id {get; set;}
public int quantity {get; set;}
public decimal item_value {get; set;}
public decimal unit_price {get; set;}
public decimal adjusted_price {get; set;}
public string product_image {get; set;}
public string product_name {get; set;}
public string product_size {get; set;}
public string product_colour {get; set;}
public string preorder_status {get; set;}
public int item_status_id {get; set;}
public string order_item_status_title {get; set;}
public int? Delivery_id {get; set;}
public int? Delivery_band_id {get; set;}
public int shipping_carrier_id {get; set;}
public string carrier_name {get; set;}
public string url {get; set;}
public string tracking_code {get; set;}
public bool printed_for_tracking {get; set;}
public bool printed_for_dispatch {get; set;}
public string credited_reason {get; set;}
public decimal? credited_amount {get; set;}
public bool refunded {get; set;}
public string refunded_reason {get; set;}
public bool exchanged {get; set;}
public string exchanged_reason {get; set;}
public DateTime dispatched_date {get; set;}
public bool? change_quantity {get; set;}
public bool awaiting_stock {get; set;}
public int? parent_id {get; set;}
public bool suburban {get; set;}
public DateTime created_on {get; set;}
public DateTime updated_on {get; set;}
public bool? deleted {get; set;}
}

miercuri, 12 octombrie 2011

MS-SQL script to generate update statements for rtrim and ltrim

Recently I did a bulk insert into a table from a CSV file and this data had trailing spaces. I didn't notice until some email addresses look like weren't valid.

I read this article which explains when the data is trimed or not

Since I had many columns to update I needed to find another solution to write/generate the update statements for "update table set column = rtrim(ltrim(column))"


declare @table_name varchar(150) = 'dbo.Member'
declare @stmt nvarchar(max)



set @stmt =
(
select '[' + c.name + '] = rtrim(ltrim([' + c.name + ']))' + ',' + char(10) + char(9)
from
dbo.syscolumns c
inner join dbo.systypes st ON st.xusertype = c.xusertype
inner join dbo.systypes bt ON bt.xusertype = c.xtype
where
c.id = object_id(@table_name,'U') and (bt.name = 'varchar' or bt.name = 'nvarchar')

for xml path ('')
)
if @stmt is not null
begin

set @stmt = 'update ' + @table_name + char(10) + 'set ' + substring(@stmt, 0, len(@stmt) - 2)
execute sp_executesql @stmt
end

luni, 10 octombrie 2011

Update between two tables when there is no relation between them

I needed a SQL statement which fills the null values from the second column of #T1 table with values from #T2(C1).

There is no foreign key or match between the columns of those two tables.

I found two approaches:

1. Using CTE

create table #T1 (C1 varchar(10), T2C1 varchar(10))
create table #T2 (C1 varchar(10))

insert into #T1 values ('A1', '1')
insert into #T1 values ('A2', null)
insert into #T1 values ('A3', null)
insert into #T1 values ('A4', '4')
insert into #T1 values ('A5', null)

insert into #T2 values ('a')
insert into #T2 values ('b')

;with t2 as
(
select C1, row_number() over (order by C1) as Index2
from #T2
)
,t1 as
(
select T2C1, row_number() over (order by C1) as Index1
from #T1
where T2C1 is null
)
update t1
set t1.T2C1 = t2.C1
from t2
where t1.Index1 = t2.Index2

select * from #T1

drop table #T1
drop table #T2

2. With Derived Tables

create table #T1 (C1 varchar(10), T2C1 varchar(10))
create table #T2 (C1 varchar(10))

insert into #T1 values ('A1', '1')
insert into #T1 values ('A2', null)
insert into #T1 values ('A3', null)
insert into #T1 values ('A4', '4')
insert into #T1 values ('A5', null)

insert into #T2 values ('a')
insert into #T2 values ('b')

update #T1
set T2C1 = cj.C1
from #T1
join (select T2C1, row_number() over (order by C1) as Index1, C1
from #T1
where T2C1 is null) ci on ci.C1 = #T1.C1
join (select C1, row_number() over (order by C1) as Index2
from #T2) cj on ci.Index1 = cj.Index2

select * from #T1

drop table #T1
drop table #T2

Update
3.From SO, with table variables

create table #T1 (C1 varchar(10), T2C1 varchar(10))
create table #T2 (C1 varchar(10))

insert into #T1 values ('A1', '1')
insert into #T1 values ('A2', null)
insert into #T1 values ('A3', null)
insert into #T1 values ('A4', '4')
insert into #T1 values ('A5', null)

insert into #T2 values ('a')
insert into #T2 values ('b')


DECLARE @Target TABLE
(
MyId INT IDENTITY(1,1) PRIMARY KEY
,T1_pk varchar(10) NOT NULL UNIQUE
);
INSERT @Target (T1_pk)
SELECT C1
FROM #T1
WHERE T2C1 IS NULL;

DECLARE @Source TABLE
(
MyId INT IDENTITY(1,1) PRIMARY KEY
,C1 VARCHAR(10) NOT NULL
);
INSERT @Source (C1)
SELECT C1
FROM #T2;

UPDATE #T1
SET T2C1 = src.C1
FROM #T1 t
INNER JOIN @Target trg ON t.C1 = trg.T1_pk
INNER JOIN @Source src ON trg.MyId = src.MyId;

select * from #T1

drop table #T1
drop table #T2

marți, 23 august 2011

CKEditor m.lang.contextmenu is undefined

I got the error "m.lang.contextmenu is undefined" while I was installing CKEditor on an ASP .Net website and trying to use a minimum setup.

I supposed the "ckeditor/lang/en.js" is enough, but, as pointed here, the editor doesn't download en.js by default, so it needs to be set on config.js

CKEDITOR.editorConfig = function (config) {
config.language = "en.js";
};

If this is not set, the editor is trying to load "the language that best fit the user language" using browser detection, so this can by any language (for sure, supported by CKEditor). That's why the editor could work with a browser, but not work with other browser, on the same machine.

joi, 28 iulie 2011

Encapsulating Sets of Properties in Complex Types, convenient or not?

With EF we can group properties into Complex Properties. For example I'm using audit information on all my entities, like CreatedOn, UpdatedOn, Deleted and Enabled and I grouped them into a ComplexType named Audit. A customer can have an InvoiceAddress and a DeliveryAddress of type Address(Street1, Street2, County, Town Postcode).




This is nice, but I encountered some problems with the updates.
As MSDN says "When any property is changed anywhere in the object graph of a complex type, the property of the parent type is marked as changed and all properties in the object graph of the complex type are updated when SaveChanges is called."
So if the UpdatedOn is changed only, the EF will "update" and CreatedOn, Enabled, Deleted properties when the SaveChanges is called. This means the update statement will update UpdatedOn column with the new value and the CreatedOn, Enabled and Deleted with the values present in the Object Graph:
Let's create first a customer

var customer = new Customer
{
Email="adrian@domain.com",
AuditInfo = new Audit
{
CreatedOn = DateTime.Now,
UpdatedOn = DateTime.Now,
Enabled = true,
Deleted = false
}
};
Customers.AddObject(customer);
SaveChanges();

Now let's see how the update behaves:

var customer = Customers.First(c=>c.Email=="adrian@domain.com");
customer.AuditInfo.Enabled = false;
customer.AuditInfo.UpdatedOn = DateTime.Now;
SaveChanges();


SELECT TOP (1)
[Extent1].[CustomerId] AS [CustomerId],
[Extent1].[Email] AS [Email],
[Extent1].[Enabled] AS [Enabled],
[Extent1].[Deleted] AS [Deleted],
[Extent1].[CreatedOn] AS [CreatedOn],
[Extent1].[UpdatedOn] AS [UpdatedOn]
FROM [dbo].[Customer] AS [Extent1]
WHERE 'adrian@domain.com' = [Extent1].[Email]
GO

-- Region Parameters
DECLARE @0 Bit = 0
DECLARE @1 Bit = 0
DECLARE @2 DateTime2 = '2011-07-28 14:46:42.1570000'
DECLARE @3 DateTime2 = '2011-07-28 15:14:09.2868054'
DECLARE @4 Int = 5
-- EndRegion
update [dbo].[Customer]
set [Enabled] = @0, [Deleted] = @1, [CreatedOn] = @2, [UpdatedOn] = @3
where ([CustomerId] = @4)

So the update used the new values for UpdatedOn and Column and for the Deleted and CreatedOn values it used the ones from database, via Customers.First call.

Now the question is: how the update will behave when using Attach method? Attach method will save a query to the database when the Key value is known (ie. Id).

var customer = new Customer { CustomerId = 5 };
Customers.Attach(customer);
customer.AuditInfo.Enabled = false;
customer.AuditInfo.UpdatedOn = DateTime.Now;
SaveChanges();


-- Region Parameters
DECLARE @0 Bit = 0
DECLARE @1 Bit = 0
DECLARE @2 DateTime2 = '0001-01-01 00:00:00.0000000'
DECLARE @3 DateTime2 = '2011-07-28 15:20:42.4672941'
DECLARE @4 Int = 5
-- EndRegion
update [dbo].[Customer]
set [Enabled] = @0, [Deleted] = @1, [CreatedOn] = @2, [UpdatedOn] = @3
where ([CustomerId] = @4)

As MSDN says, it updated all properties. Of course, it used the ones present in memory, in this case the default values '0001-01-01 00:00:00.0000000' for CreatedOn and 0 for Deleted.

Fortunately, this update raised an error "The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.", but in the case of the Address type, where the properties are Strings, it would set on nulls, and if there is no constraint on database, there would be no error..

The things were very very strange, when I was updating the Entity via a FormView and an EntityDataSource. The issue was the EntityDataSource had the property EnableFlattening="false". In this case, the update behaved like the Attach method, putting the default values instead of the original ones. With the wrapper around the entity, the update worked correctly. MSDN says "If your conceptual model includes foreign key properties and does not contain complex types, the EntityDataSource designer will set EnableFlattening to false at design-time to avoid creating entity wrapper objects."

Did you build your model based on Complex Types? Is it convenient? Think again :)

miercuri, 27 iulie 2011

Remotely Install EntityFramework 4.1 with psexec and gacutil

I updated an website to use EntityFramework 4.1 Update 1. While I had no problems installing it on my dev machine, on the production machine the installer wasn't able to install the EntityFramework.dll on GAC. The reason is simple, there is no SDK installed.

I can't RDC on the production server, but I have a hidden shared folder, named "adrian$".

To install EntityFramework on the production machine I needed psexec, able to start and run gacutil. As I said, gacutil was not installed, because there is no SDK, so I copied the .Net 4.0 version (from C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools) on my shared folder "adrian$\gacutil" together with gacutlrc.dll from 1033 folder.
Next thing to do was to copy the EntityFramework.dll. Summarized, the new remote files looks like:

\\server\adrian$\gacutil\1033\gacutlrc.dll
\\server\adrian$\gacutil\gacutil.exe
\\server\adrian$\gacutil\gacutil.exe.config

\\server\adrian$\EntityFramework.dll

And the psexec commands look like:
1. To see if EF is installed:

psexec \\server -u User -p Password "\\server\adrian$\gacutil\gacutil.exe" /l EntityFramework



2.Install the EntityFramework on GAC

psexec \\server -u User -p Password "\\server\adrian$\gacutil\gacutil.exe" /i "\\server\adrian$\EntityFramework.dll"

joi, 21 iulie 2011

IIS 7.5, HTTPS Bindings and ERR_CONNECTION_RESET

Having an website with HTTP and HTTPS bindings, running on my local IIS 7.5 server, I encountered this error with Chrome, Error 101 (net::ERR_CONNECTION_RESET) while trying to access it with HTTPS protocol. I checked the IIS and the bindings were fine, both protocols were set and self-signed certificate didn't expire yet.

Since the website it wasn't accessible on the HTTPS protocol and everything seems ok at the IIS level, I suspected there was something which it can be fixed with the netsh command.

The first thing to do was to list the SSL server certificate bindings:

netsh http show sslcert

As I expected, there was nothing shown. To "add a new SSL server certificate binding and corresponding client certificate policies for an IP address and port" (from help), netsh can be used with some basic parameters: ipport, certhash and appid.

The certhash value can be read either from ISS Manager (Manage server\Server Certificates, select a certificate, click View in the right menu, Details\Thumbprint, copy the value somewhere and replace the blanks between the groups), either using the following command:


certutil -store MY

which outputs:

Serial Number: 59e762ee4c6bda874fed1c915d26e521
Issuer: CN=adi-PC
NotBefore: 21.07.2011 2:16
NotAfter: 21.07.2012 3:00
Subject: CN=adi-PC
Signature matches Public Key
Root Certificate: Subject matches Issuer
Template:
Cert Hash(sha1): dc ab 84 55 bf 75 5c ad a4 b9 1d a6 64 45 68 b3 11 69 f0 20
Key Container = ea4cc866-f5b9-4737-a18e-1724e02961ba
Unique container name: 0e2c5f1fd1fe7a2461b77daf1973b1cb_d924ef92-4440-4132-82f8-cc223fca6bb8
Provider = Microsoft RSA SChannel Cryptographic Provider
Encryption test passed
CertUtil: -store command completed successfully.


The appid is any valid Guid surrounded with {}. I used PowerShell to create a new one, though I could get the "Key Container" value.

The command looks like:

netsh http add sslcert ipport=0.0.0.0:443 certhash=dcab8455bf755cada4b91da6644568
b31169f020 appid={ea4cc866-f5b9-4737-a18e-1724e02961ba}


The output of "netsh http show sslcert" is now:

SSL Certificate bindings:
-------------------------

IP:port : 0.0.0.0:443
Certificate Hash : dcab8455bf755cada4b91da6644568b31169f020
Application ID : {ea4cc866-f5b9-4737-a18e-1724e02961ba}
Certificate Store Name : (null)
Verify Client Certificate Revocation : Enabled
Verify Revocation Using Cached Client Certificate Only : Disabled
Usage Check : Enabled
Revocation Freshness Time : 0
URL Retrieval Timeout : 0
Ctl Identifier : (null)
Ctl Store Name : (null)
DS Mapper Usage : Disabled
Negotiate Client Certificate : Disabled


The ERR_CONNECTION_RESET error disappeared :)


Note: I don't do this kind of things day by day, after all, I'm only a developer. This was not a simple thing for me to do, actually it took about two hours of google-ing, this when netsh wasn't a new thing to me, a bit frustrating. But how I can test the 3D Secure integration on an eshop when my SSL is down? Can't! So I needed to have it working.

marți, 28 iunie 2011

Practical Example for Abstract Classes



using System;

namespace AbstractClasses
{
public abstract class Messager
{
protected string _recipient;
protected string _message;
public Messager(string recipient, string message)
{
_recipient = recipient;
_message = message;
}
public void ProcessMessage()
{
LogMessageLength();
// the code from here
var isValid = false;
if (ValidateRecipient())
{
isValid = true;
SendMessage();
}
// to here will be implemented by the concrete classes
if (isValid)
NotifyTheServiceOwner("The message was correctly sent");
else
NotifyTheServiceOwner("The message was NOT sent");
}
protected abstract void SendMessage();
protected abstract bool ValidateRecipient();
private void LogMessageLength()
{
// log the message
Console.WriteLine("Sending a message of size: {0}", _message.Length);
}
private void NotifyTheServiceOwner(string note)
{
// notify the service owner via email
}
}
public class SmsMessager : Messager
{
public SmsMessager(string _recipient, string _message)
: base(_recipient, _message)
{ }
protected override bool ValidateRecipient()
{
// validate the phone number
return true;
}
protected override void SendMessage()
{
// use some SMS service to send the message
}
}
public class EmailMessage : Messager
{
public EmailMessage(string _recipient, string _message)
: base(_recipient, _message)
{ }
protected override bool ValidateRecipient()
{
// validate the email address
return true;
}
protected override void SendMessage()
{
// use the .Net classe to send an email
}
}

class Program
{
static void Main(string[] args)
{
var messagers = new Messager[]
{
new EmailMessage("adrian@domain.com","Hello"),
new SmsMessager("+4074312122", "Hi"),
new EmailMessage("rahul@domain2.com", "Hello rahul")
};
foreach (var messager in messagers)
{
messager.ProcessMessage();
}
}
}
}

sâmbătă, 25 iunie 2011

Table Per Hierarchy Inheritance with Column Discriminator and Associations used in Derived Entity Types

In this article I will show how to model a table per hierarchy, a bit more complex than I found in books or other articles. I'm sure this model is present in real lif,e but I really didn't have the luck to find an example on the web when I needed it most. The complexity of this model is given by the Foreign Keys ( the Associations) which need to be placed in the derived entities types and the fact the discriminator depends on more than one column. The first problem I could fix, but the next one, with the discriminator based on two or three nullable columns I couldn't do it, unless if I use a single discriminator column (ie ItemType or something).


The database is very simple. It is designed for an eshop which sells products, services and also has some nice packages, that combines products and services and offers them for good prices compared with if they would be bought alone. The products and services are very different in terms of how data describes them, so the decision was to store them in separate tables. An invoice will have totals, etc and its invoice lines. The invoice line table will link exclusively to a product or a service or a product/service in a package. So for sample if an invoice line has the ProductID set and the PackageID set, then it means the customer bought a package with that product. If an invoice line has only the ProductID set, then it means the customer bought a standalone product. Same for a service. An invoice line can't have both the ProductID and ServiceID set. I hope this structure is clear.



I'm starting with a new and empty Entity Model. As a first step I Update Model from Database and add only the InvoiceLine and Product tables. I'm check the “Pluralize or singularize generated object names” and “Include foreign key columns in model”.




The association from Product and InvoiceLine is 0..1 to many. Since the ProductID is null, makes sense: an invoice line could have or not a product. The next thing is to create a new EntityType called ProductLine, derived from InvoiceLine:
1.right-click the design surface, select Add->Entity, name it ProductLine and set the BaseType to InvoiceLine.
2.right-click the ProductLine, click Table Mapping and on Mapping Details, Add a Table or View and select InvoiceLine
3.cut and paste the ProductID from InvoiceLine to ProductLine
4.map in Mapping Details the ProductID column to ProductID value/property
5.right-click the ProductLine entity, Table Mapping, click “Add a condition” and add the conditions When ProductID is Not Null and PackageID is Null.
6.right-click ProductID property, click Properties and set Nullable to False. Since this derived entity is for Product there is no reason to let the Product is nullable.
7.Delete the 0..1 - * association between Product and InvoiceLine
8.right-click the design surface, add Association. Choose Product on the left side and ProductLine on the right side, so will see “Product can have * (Many) instances of ProductLine.”. Uncheck Add foreign key properties to 'ProductLine' Entity. Click OK.
9. double-click the new association. Choose Product as Principal, ProductID as Dependent Properties.
10. Save and Compile.



Before going further, one more thing. I can't create and save ProductLine because there is no InvoiceEntity added yet. So, right click the design surface, Update Model from Database, Add the Invoice table to the model. This is also a good test for Update Model from Database function which sometimes can broke previously made changes. See how I can use the entities:


var invoice = new Invoice();
var product = new Product {Name = "Product"};
var productLine = new ProductLine {Invoice = invoice, Product = product, Title = "Shoe Product",Discriminator="P"} ;
InvoiceLines.AddObject(productLine);
SaveChanges();

var query = from p in InvoiceLines.OfType<ProductLine>().Include("Product")
select p;

query.Dump();

During this I encountered some problems. One of them was with the Association between the Product and the ProductLine, I was getting this error:



Problem in mapping fragments starting at lines 135, 145, 154:Foreign key constraint 'FK_InvoiceLine_product' from table InvoiceLine (ProductID) to table Product (ProductID):: Insufficient mapping: Foreign key must be mapped to some AssociationSet or EntitySets participating in a foreign key association on the conceptual side.”

This was because in the StorageModel there was present this Foreign Key, but in the conceptual model there was no Association either between the Product and InvoiceLine or between Product and newly created ProductLine. This association must have a ReferentialConstraint also.



Another error was:
“Multiplicity is not valid in Role 'Product' in relationship 'ProductProductLine'. Because all the properties in the Dependent Role are nullable, multiplicity of the Principal Role must be '0..1'.”
This error was because when I moved the ProductID property to ProductLine, I didn't set its Nullable property to false.

Other one was:
“Problem in mapping fragments starting at lines 153, 163:EntityTypes DB.InvoiceLine, DB.ProductLine are being mapped to the same rows in table InvoiceLine. Mapping conditions can be used to distinguish the rows that these types are mapped to.”

This is clear. The InvoiceLine and ProductLine entity types can't share the same rows in InvoiceLine table. This was fixed by adding the Condition ProductID is not null at the ProductLine EntityTypeMapping. I added also and the condition PackageID is null, because I don't want these rows, they belong to a package.



The next step is to create the ServiceLine, ProductPackageLine and ServicePackageLine entity types.
I start with ServiceLine because ServinceLine and ProductLine will be base types for ProductPackageLine and ServicePackageLine. For ServiceLine EntityType I will repeat the steps for ProductLine, after I will add the Service table in the model.




Some tests with LinqPad:


var invoice = Invoices.First();
var product = new Product {Name = "Product 2"};
var productLine = new ProductLine {Invoice = invoice, Product = product, Title = "Shoe Product 2",Discriminator="P"} ;
var service = new Service {Name = "Service 2"};
var serviceLine = new ServiceLine {Invoice = invoice, Service = service, Title = "Database Services",Discriminator="S"} ;
InvoiceLines.AddObject(productLine);
InvoiceLines.AddObject(serviceLine);

SaveChanges();

var queryP = from p in InvoiceLines.OfType<ProductLine>().Include("Product")
select p;

queryP.Dump();

var queryS = from p in InvoiceLines.OfType<ServiceLine>().Include("Service")
select p;

queryS.Dump();

The next challenge is to create ServicePackageLine and ProductPackageLine Entity types.
1. Update Model from Database, add Package
2. Created a new EntityType called ProductPackageLine, base type is ProductLine (not InvoiceLine, because I want to access the Product via ProductLine.Product)
3. Cut and paste the PackageID property from InvoiceLine to ProductPackageLine
and map the column PackageID to PackageID property.
4. Create the “Is Not Null” condition for PackageID in the ProductPackage Mappings
Obs: I saw this error:
“There is no property with name 'PackageID' defined in type referred by Role 'InvoiceLine'.” This is because I just deleted the property PackageID from InvoiceLine. Basically I need to “move” also the Association between InvoiceLine and Package to ProductPackageLine and Package.
5. I “moved” the association


It seems to me kind obviously that the condition PackageID is not null would suffice, but there is not like I expected:
“Problem in mapping fragments starting at lines 265, 273:Two entities with different keys are mapped to the same row. Ensure these two mapping fragments do not map two groups of entities with different keys to the same group of rows.”
Let's see the conditions:
ServiceLine : ServiceID is not null and PackageId is null
ProductLine : ProductID is not null and PackageID is null
ProductPackageLine via ProductLine: PackageID is not null
Here EF gets confused with the condition PackageID is not null and can't tell if the the rows described by an EntityType can mix with other rows in the set of another EntityType. In my opinion they don't mix, but I needed to made
the decision to add the discriminator column (This was present from the beginning of this article, but it could been added later via Update Model from Database).
The steps are:
1. delete all conditions from derived entity types.
2. add the new conditions Discriminator='P' at ProductLine, Discriminator='S' at ServiceLine and Discriminator='PP' at ServicePackageLine
At compilation I got the error:
“Problem in mapping fragments starting at lines 257, 265, 276, 283:Column InvoiceLine.Discriminator has no default value and is not nullable. A column value is required to store entity data.
An Entity with Key (PK) will not round-trip when:
(PK is in 'InvoiceLines' EntitySet AND Entity is type [DB.InvoiceLine])”

This was cleared by doing the InvoiceLine Entity Type abstract. At the next compilation I got the following error:
“Problem in mapping fragments starting at line 257:Condition member 'InvoiceLine.Discriminator' with a condition other than 'IsNull=False' is mapped. Either remove the condition on InvoiceLine.Discriminator or remove it from the mapping.”
Simply as it says I need to remove the Discriminator property from InvoiceLine, which did.

And the final model is:


Too bad I needed to change the table's structure for this model. I could also let the InvoiceLine entity like it was, but I would have to take extra care for wrong data, like having an item with a Product and Service set. Also maybe I'm doing something wrong with the Null Conditions. Again, the scenario is Is Null - Not Null, Not Null - Is Null, Both Not Null, but I had no success with it.

I'm new to EF, playing with it for about two months, I spent almost 6 hours with this model, but mainly because of the lack of experience. It was a good one, I didn't really paid so much attention to modelling until these days. I learned a bit about conditions, inheritance and how please the storage model with the conceptual model regarding to associations.

vineri, 3 iunie 2011

Working with TIME type in SQL and ASP .Net

Scenario: a teacher schedules his courses on a random different dates in the near future, but he always know the start time. For sample in the current week he can schedule a course for Tuesday and Friday, at 08:00 AM.
In a database there would be the following tables:
1. course (title, summary, ..)
2. course_schedule(course_id, location, start_time) where data about that schedule is preserved( ie. location)
3. course_schedule_span(schedule_id, course_date) for storing the dates when the schedule spans

The dates have always the same start time, I knew this before designing the database, so in the first time I let the time in the course_schedule_span table, in course_date column (ie. 31/12/2011 16:00). Later the teacher wanted to set and the end time so I decided to move the start time into course_schedule table and this new end time field to add it there also.
The first attempt was to store the time in a varchar(5) column, this would suffice for storing like hh:mm values. Later I changed my mind, when I found out about the TIME type from SQL Server.

The minimal option to store hh:mm is TIME(0) which means the fractional seconds precision is 0 ( size is 3 bytes, less than the 5 bytes used by varchar(5)).

The first task was to update the time from the existing courses in the hh:mm format (just to be sure there are no seconds somewhere).


update course_schedule
set start_time = (select top 1
convert(time(0),substring(convert(varchar, convert(time(0),course_schedule_span.course_date)),1,5))
from course_schedule_span
where course_schedule_span.schedule_id = course_schedule.schedule_id)

Extract time from date with convert(time(0)), convert to varchar to substring the hour and minute and then convert back to time(0).

The next thing was the update the Entity Framework model, I tried with Update model from database, but it didn't add the newly created columns, maybe because it can't handle TIME types, so I used "Add scalar property" function, I set the type to Time and with "Table mappings" I set the rest of the mappings.

The page needs to update only the hours and the minutes, not the seconds, so the Bind functions need to use the format parameter to show only the hour and the minutes.
Here I had some problems. First was an exception "Input string was not in a correct format", which occurs when I used the following expression
 
Text='<%# Bind("end_time","{0:hh:mm}") %>'

After some tests I figured out the semicolon it caused this so I escaped it with \.
However, when I used the Eval construct, in other page, with the same format, I got the following error "CS1009: Unrecognized escape sequence". A bit confused here, and when I checked the pages's generated class I saw that the generator it escapes the backslash when is in Bind constructs, but it doesn't do this for Eval constructs.

Eval needs the format string to be escaped
Line 1877:         public void @__DataBinding__control28(object sender, System.EventArgs e) {
ASP.controls_ldbtextfield_ascx dataBindingExpressionBuilderTarget;
System.Web.UI.WebControls.FormView Container;
dataBindingExpressionBuilderTarget = ((ASP.controls_ldbtextfield_ascx)(sender));
Container = ((System.Web.UI.WebControls.FormView)(dataBindingExpressionBuilderTarget.BindingContainer));

#line 56 "...\schedules\event-schedule-details.aspx"
dataBindingExpressionBuilderTarget.Text = global::System.Convert.ToString( Eval("start_time","{0:hh\:mm}") , global::System.Globalization.CultureInfo.CurrentCulture);

#line default
#line hidden
}

Bind escapes the string used as a format parameter

Line 1950: public void @__DataBinding__control29(object sender, System.EventArgs e) {
ASP.controls_ldbtextfield_ascx dataBindingExpressionBuilderTarget;
System.Web.UI.WebControls.FormView Container;
dataBindingExpressionBuilderTarget = ((ASP.controls_ldbtextfield_ascx)(sender));
Container = ((System.Web.UI.WebControls.FormView)(dataBindingExpressionBuilderTarget.BindingContainer));
if ((this.Page.GetDataItem() != null)) {

#line 57 "...\schedules\event-schedule-details.aspx"
dataBindingExpressionBuilderTarget.Text = global::System.Convert.ToString(this.Eval("start_time", "{0:hh\\:mm}"), global::System.Globalization.CultureInfo.CurrentCulture);

#line default
#line hidden
}
}

So, to format a TimeSpan in hh:mm style, Bind needs non-escaped format and Eval needs an escaped format.

Text='<%# Bind("start_time","{0:hh\:mm}") %>'
and
Text='<%# Eval("start_time",@"{0:hh\:mm}") %>'

marți, 31 mai 2011

About the "The Controls collection cannot be modified because the control contains code blocks" symptom

As the error message says, if a control contains code blocks (but not databinding expressions, ie <%# ..), its Controls collection can't be altered, by adding another control at runtime using Controls.Add. However, this rule doesn't apply for child controls, for example if a control uses other control with code blocks, then the first control's Controls collection (the parent's one) has no limitations.

Usually this error is encountered mostly when working with the <head runat="server".
Suppose there is a code block which uses some code to decide which protocol to use to download some external scripts, depending on the connection used by the client.
 <head runat="server">
<% if (!HttpContext.Current.Request.IsSecureConnection)
{ %>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script>
<% }
else
{%>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script>
<% } %>
</head>
.. and later in the code behind it is decided to add some meta information using
((HtmlHead)Page.Header).Controls.Add(new HtmlMeta {....});

This will raise the above error, the collection is altered and the collection "contains" code blocks.

Less obviously, or at least for a beginner, is when code blocks are used on templated controls, for example in a LayoutTemplate. This time the Controls collection is modified by the control's creator( ASP .Net team or a third party), not by the developer.
     <asp:ListView ID="lvItems" runat="server" DataSourceID="edsCourses">
<LayoutTemplate>
<h2>Search results <%= !String.IsNullOrEmpty(Request.Params["search"]) ? "for &quot;" + HttpUtility.HtmlEncode(Request.Params["search"]) + "&quot;" : String.Empty %></h2>
..............

Why using code blocks, anyway? Well, some would say this is an anti-pattern, but I would like to consider it a nice feature, a painless one. In the previous ListView I could use an <asp:Literal ID="ltSearchTerm and a handler for ListView.DataBound event, where I would do something like ((Literal)lvItems.FindControl("ltSearchTerm")).Text = ... . So: add a handler, find the control plus additional checks for null and set the Text property. A good/defensive practice, but might be anti-RAD. Of course, if the project is an Web Application type, this needs to be compiled.

I've seen on web several techniques to safely use code blocks.
  1. Wrap method, using placeholders
  2. UserControl method
  3. Call on DataBind()

1. Wrap Method: wrap the code block with an <asp:PlaceHolder
<head runat="server">       
<asp:PlaceHolder runat="server">
<% if (!HttpContext.Current.Request.IsSecureConnection)
{ %>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script>
<% }
else
{%>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script>
<% } %>
</asp:PlaceHolder>
</head>

In this way the code block is not considered part to the Header.Controls collection, instead is a child of that PlaceHolder and this one a child of Header. The PlaceHolder is good because it doesn't emit any html. The Controls collection can be changed, which means the metadata can be added with no exception raised.
In a master page I saw the suggestion to wrap with an <asp:ContentPlaceHolder. I would use this if it is going to be used further in the pages. In this case the content will be replaced.

2. User Control method

The idea is to move the code block into an user control. This it doesn't need to have any code behind so the file ascx.cs and ascx.designer.cs can be removed.
<%@ Control Language="C#" AutoEventWireup="true" %>
<h2>Search results <%= !String.IsNullOrEmpty(Request.Params["search"]) ? "for &quot;" + HttpUtility.HtmlEncode(Request.Params["search"]) + "&quot;" : String.Empty %></h2>

and use as

<asp:ListView ID="lvItems" runat="server" DataSourceID="edsCourses">
<LayoutTemplate>
<ldb:SearchResultsTopHeader ID="ldbSearchResultsTopHeader" runat="server" />

I prefer this to the placeholder when the control will be used in more than one place.

3. Call on DataBind()

Any expression <%= is transformed in a binding expression, <%# and the parent control calls DataBind() (ie. Page.Header.DataBind()). This works on header, but for sure it doesn't work for a LayoutTemplate. And maybe more important, the code blocks in here <% ... %> could be very complicated and not so easy to transform them in databinding expressions. .. And there is introduced the call on DataBind() also.

joi, 26 mai 2011

miercuri, 6 aprilie 2011

My Birthday

Today is my birthday and because today my thoughts are only about myself, I had a curiosity about in which years I did celebrate my birthday on Wednesdays ( I like this day of week).
With the following LINQ query I found the answer

from i in Enumerable.Range(0,29)
where (new DateTime(i + 1983,4,6).DayOfWeek) == DayOfWeek.Wednesday
select new { year = i + 1983, age = i }

which is..

Year Age
1983 0
1988 5
1994 11
2005 22
2011 28

And because my curiosity about me and only me goes mad, I wanted to find out more about each day of week and my birthdays.

Enumerable.Range(0,29).ToLookup(i =>new DateTime(i + 1983,4,6).DayOfWeek, i=>new {year = i + 1983,age = i}).OrderBy(d=>(int)d.Key)

click on the image to see it in full size

Thanks to LINQ Pad.

Virusii, messengerul si clinicile particulare

Printre pietenii de pe YM, am si un contact de la o clinica particulara din Iasi. Cand aveam nevoie de o programare, mi-era muuult mai simplu sa o fac pe messenger, decat la telefon.

Dar, cum "virusurile" informatici au pus stapanire pe calculatorul din "front office", clinica s-a pricopsit cu o problema de PR, de care nu prea vrea sa scape prea curand.