Navigation
Links

Powered by Squarespace

Entries in .NET (27)

Tuesday
Oct072008

c# Language request for properties

Auto-Implemented properties are great, until you need to implement custom get or set logic. I love the ability to make the field an implementation detail, until you need to implement the property. What if you could continue to hide the field, like this:
public string FirstName {
get {
// do more stuff, like lazy init the field
if (field == null)
field = "Unknown";
return field;
}
set {
field = value;
}
}
A new keyword, field, references the compiler generated property’s backing field. Also, for readonly fields:
public readonly string Id {
get {
return field;
}
set { // private is implied
// do more stuff, like don't accept null
if (value == null)
value = string.Empty;
field = value;
}
}
Where the property would need to be set in the constructor (like read-only fields) as the backing field would be marked read-only. For simplicity, the implementation would use simple property syntax while the compiled output would involve a read-only field, a truly read-only property and a constructor that executes the property's set body via a static method call each time the field is set in the constructor.

Please rate and validate this sugestion at the MSDN Microsoft Product Feedback Center.
Wednesday
Sep102008

LINQ to SQL produces incorrect TSQL when using UNION or CONCAT

When a LINQ to SQL query contains a Union or Concat with a second query, and the second query references a column twice, a SqlException will occur.

var a = from address in dc.Addresses
select new {
ID = address.AddressID,
Address1 = address.AddressLine1,
Address2 = address.AddressLine2,
};
var b = from address in dc.Addresses
select new {
ID = address.AddressID,
Address1 = address.AddressLine1,
Address2 = address.AddressLine1, // notice AddressLine1 repeated
};
var q = a.Take(10).Union (b.Take(10));
q.ToArray ();


SqlException: All the queries in a query expression containing a UNION operator must have the same number of expressions in their select lists.

SELECT [t2].[AddressID] AS [ID], [t2].[AddressLine1] AS [Address1], [t2].[AddressLine2] AS [Address2]
FROM (
SELECT TOP (10) [t0].[AddressID], [t0].[AddressLine1], [t0].[AddressLine2]
FROM [Person].[Address] AS [t0]
UNION
SELECT TOP (10) [t1].[AddressID], [t1].[AddressLine1]
FROM [Person].[Address] AS [t1]
) AS [t2]


Notice the third SELECT statement is only selecting two columns instead of the required three.

Please rate and validate this bug at the MSDN Microsoft Product Feedback Center so Microsoft responds with a solution or workaround.
Tuesday
Sep092008

Extending LINQ to SQL

Last year, Scott Guthrie stated “You can actually override the raw SQL that LINQ to SQL uses if you want absolute control over the SQL executed”, but I can’t find documentation describing an extensibility method.

I would like to modify the following LINQ to SQL query:
using (NorthwindContext northwind = new NorthwindContext ()) {
var q = from row in northwind.Customers
let orderCount = row.Orders.Count ()
select new {
row.ContactName,
orderCount
};
}

Which results in the following TSQL:
SELECT [t0].[ContactName], (
SELECT COUNT(*)
FROM [dbo].[Orders] AS [t1]
WHERE [t1].[CustomerID] = [t0].[CustomerID]
) AS [orderCount]
FROM [dbo].[Customers] AS [t0]

To:
using (NorthwindContext northwind = new NorthwindContext ()) {
var q = from row in northwind.Customers.With (
TableHint.NoLock, TableHint.Index (0))
let orderCount = row.Orders.With (
TableHint.HoldLock).Count ()
select new {
row.ContactName,
orderCount
};
}

Which would result in the following TSQL:
SELECT [t0].[ContactName], (
SELECT COUNT(*)
FROM [dbo].[Orders] AS [t1] WITH (HOLDLOCK)
WHERE [t1].[CustomerID] = [t0].[CustomerID]
) AS [orderCount]
FROM [dbo].[Customers] AS [t0] WITH (NOLOCK, INDEX(0))

Using:
public static Table<TEntity> With<TEntity> (
this Table<TEntity> table,
params TableHint[] args) where TEntity : class {

//TODO: implement
return table;
}
public static EntitySet<TEntity> With<TEntity> (
this EntitySet<TEntity> entitySet,
params TableHint[] args) where TEntity : class {

//TODO: implement
return entitySet;
}

And

public class TableHint {
//TODO: implement
public static TableHint NoLock;
public static TableHint HoldLock;
public static TableHint Index (int id) {
return null;
}
public static TableHint Index (string name) {
return null;
}
}


Using some type of LINQ to SQL extensibility, other than this one. Any ideas?

Please comment on this question over at StackOverflow.com
Wednesday
Apr092008

LINQ to SQL - code generation bug

The code generation performed by MSLinqToSQLGenerator or SQLMetal generates weird property code. For example, in AdvantureWorks, the table Product has a column ProductLine. Using the tools that come with LINQ to SQL, this column translates to a property:
[Column(Storage="_ProductLine", DbType="NChar(2)")]
public string ProductLine
{
get
{
return this._ProductLine;
}
set
{
if ((this._ProductLine != value)) {
this.OnProductLineChanging(value);
this.SendPropertyChanging();
this._ProductLine = value;
this.SendPropertyChanged("ProductLine");
this.OnProductLineChanged();
}
}
}
The odd code involves the SendPropertyChanging() method call. This method call should pass the name of the property, just like the SendPropertyChanged() method call, according to the documentation. Another interesting detail: The OnProductLineChanging and OnProductLineChanged partial method calls are out of order:

  1. Call OnProductLineChanging() partial method

  2. Raise PropertyChanging event, but don’t tell which property is changing – send an empty string instead

  3. Set the property’s field’s value to the specified new value

  4. Raise PropertyChanged event and specify which property is changing

  5. Call OnProductLineChanged() partial method

Why is the PropertyChanged event raised before calling the OnProductLineChanged partial method?

All classes created by LINQ to SQL add the following protected methods:

protected virtual void SendPropertyChanging() {
if ((this.PropertyChanging != null)) {
this.PropertyChanging(this, emptyChangingEventArgs);
}
}
protected virtual void SendPropertyChanged(String propertyName) {
if ((this.PropertyChanged != null)) {
this.PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
Again, what’s odd about this code is how the SendPropertyChanging() method does not have a property name parameter and sends a emptyChangingEventArgs field reference to the PropertyChanging event rather than creating a new instance of the EventArgs like the SendPropertyChanged() method call does. By creating a new instance of the EventArgs in SendPropertyChanged, it’s able to pass the property name in the constructor (like the documentation says it should).

Here is the field that is passed to all invocations of the event:
private static PropertyChangingEventArgs emptyChangingEventArgs = 
new PropertyChangingEventArgs(String.Empty);

As you can see from this constructor, the property that is changing is an empty string. Given the fact that this is a private field and should not be modified by extension methods, it’s odd that this field is not static readonly.

My guess is that the code is generated incorrectly to account for a data-binding or allocation problem. I’ve come to this conclusion by the emptyChangingEventArgs field – it reduces the object instance creation in half for each property change when there are event consumers for the changing event. The big disadvantage for event consumers is that they doesn’t know which property is changing on an object instance.

One alternative is to use PLINQO, which creates the properties correctly.

UPDATE: I have found that this has already been reported. Unfortunately, Microsoft has closed this bug and said it was by design, even though the generated code does not follow Microsoft's documentation for the PropertyChangingEventArgs class.
Friday
Nov302007

LINQ - WHERE X IN (…)

I couldn't figure out a way to perform the equivalent of WHERE Column1 IN ('A', 'B', 'C') in LINQ, where ('A', 'B', 'C') would represent an IEnumerable<T> where T is the type of Column1. So I thought it was an excellent time to write an extension method that would generate a dynamic expression tree that would add AND (Column1 == "A" OR Column1 = "B" OR ...) to the LINQ query. So I wrote the following code:
public static IQueryable<TSource> WhereIn<TSource, TKey> (
this IQueryable<TSource> source1,
Expression<Func<TSource, TKey>> keySelector,
IEnumerable<TKey> source2) {
if (null == source1)
throw new ArgumentNullException ("source1");
if (null == keySelector)
throw new ArgumentNullException ("keySelector");
if (null == source2)
throw new ArgumentNullException ("source2");
Expression where = null;
foreach (TKey value in source2) {
Expression equal = Expression.Equal (
keySelector.Body,
Expression.Constant (value, typeof (TKey))
);
if (null == where)
where = equal;
else
where = Expression.OrElse (where, equal);
}
return source1.Where<TSource> (
Expression.Lambda<Func<TSource, bool>> (
where, keySelector.Parameters));
}
An example of the usage:
var q = (from u in db.Users
where u.LastLogin > new DateTime (2007, 5, 1)
orderby u.LastLogin descending
select new { u.FirstName, u.LastName, u.UserName, u.LastLogin }
).WhereIn (u => u.UserName, new string[] { "A", "B", "C" });
A day later, I found the right way that will actually generate "WHERE X IN (...)" in LINQ to SQL thanks to Mark Blomsma.