Sergey Zwezdin


Microsoft Regional Director

Microsoft MVP
Use of enum type in ADO.NET Data Services

This the autumn was possible to communicate about ADO.NET Data Services with the Izhevsk developers community. Except other discussed questions, we have started talking about use of enum type as a part of entity which is used in service based on ADO.NET Data Services. As after that in this question was interested some more person, I decide to take out this information here.

The problem consists in the following. We will assume have decided to create service ADO.NET Data Services and to use in its source the entity containing a field of enum type. Having accessed to such service it is possible to see a strange error.

It is possible to look details of this error. For this purpose it is necessary to setup service.

[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class WebDataService1 : DataService<MyDataContext>
{

Having accessed to service again, we will see an error which says that enum type cannot be used in entities for similar services. Unfortunately, this annoying defect in ADO.NET Data Services can seriously impair a life of developers. Let's try solve this problem.

For this purpose we will create entity and enum type which we will use in service:

public enum StateEnum
{
    Normal = 1,
    Error = 2
}
 
[DataServiceKey("ID")]
public class SampleEntity
{
    public int ID { get; set; }
 
    public string Name { get; set; }
 
    public StateEnum State
    {
        get;
        set;
    }
}

Now we will create own data context and standard service ADO.NET Data Services.

public class MyDataContext
{
    private static readonly IEnumerable<SampleEntity> Entities = new List<SampleEntity>()
{

new SampleEntity()

{ID = 1, Name = "Name1", State = StateEnum.Normal},

new SampleEntity()

{ID = 2, Name = "Name2", State = StateEnum.Error},

new SampleEntity()

{ID = 3, Name = "Name3", State = StateEnum.Normal},

new SampleEntity()

{ID = 4, Name = "Name4", State = StateEnum.Normal},

new SampleEntity()

{ID = 5, Name = "Name5", State = StateEnum.Normal},

};
 
    public IQueryable<SampleEntity> Data
    {
        get
        {
            return Entities.AsQueryable<SampleEntity>();
        }
    }
}

It is clear, that with such service we will receive an error which saw at the beginning. To avoid an error we will use IgnoreProperties attribute.

[DataServiceKey("ID")]
[IgnoreProperties("State")]
public class SampleEntity
{
    public int ID { get; set; }
 
    public string Name { get; set; }
 
    public StateEnum State
    {
        get { return (StateEnum)StateValue; }
        set { StateValue = (int)value; }
    }
}

Great! The error has disappeared, but thus value of the given property is not transferred to the client.

<?xml version="1.0" encoding="utf-8" standalone="yes" ?> 
<feed xml:base="http://localhost:4321/WebDataService1.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
    <title type="text">Data</title> 
    <id>http://localhost:4321/WebDataService1.svc/Data</id> 
    <updated>2009-11-29T06:06:57Z</updated> 
    <link rel="self" title="Data" href="Data" /> 
    <entry>
        <id>http://localhost:4321/WebDataService1.svc/Data(1)</id> 
        <title type="text" /> 
        <updated>2009-11-29T06:06:57Z</updated> 
        <author>
        <name /> 
        </author>
        <link rel="edit" title="SampleEntity" href="Data(1)" /> 
        <category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
        <content type="application/xml">
            <m:properties>
                <d:ID m:type="Edm.Int32">1</d:ID> 
                <d:Name>Name1</d:Name> 
            </m:properties>
        </content>
    </entry>
    <entry>
        <id>http://localhost:4321/WebDataService1.svc/Data(2)</id> 
        <title type="text" /> 
        <updated>2009-11-29T06:06:57Z</updated> 
        <author>
        <name /> 
        </author>
        <link rel="edit" title="SampleEntity" href="Data(2)" /> 
        <category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
        <content type="application/xml">
            <m:properties>
                <d:ID m:type="Edm.Int32">2</d:ID> 
                <d:Name>Name2</d:Name> 
            </m:properties>
        </content>
    </entry>
    <entry>
        <id>http://localhost:4321/WebDataService1.svc/Data(3)</id> 
        <title type="text" /> 
        <updated>2009-11-29T06:06:57Z</updated> 
        <author>
        <name /> 
        </author>
        <link rel="edit" title="SampleEntity" href="Data(3)" /> 
        <category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
        <content type="application/xml">
            <m:properties>
                <d:ID m:type="Edm.Int32">3</d:ID> 
                <d:Name>Name3</d:Name> 
            </m:properties>
        </content>
    </entry>
    <entry>
        <id>http://localhost:4321/WebDataService1.svc/Data(4)</id> 
        <title type="text" /> 
        <updated>2009-11-29T06:06:57Z</updated> 
        <author>
        <name /> 
        </author>
        <link rel="edit" title="SampleEntity" href="Data(4)" /> 
        <category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
        <content type="application/xml">
            <m:properties>
                <d:ID m:type="Edm.Int32">4</d:ID> 
                <d:Name>Name4</d:Name> 
            </m:properties>
        </content>
    </entry>
    <entry>
        <id>http://localhost:4321/WebDataService1.svc/Data(5)</id> 
        <title type="text" /> 
        <updated>2009-11-29T06:06:57Z</updated> 
        <author>
        <name /> 
        </author>
        <link rel="edit" title="SampleEntity" href="Data(5)" /> 
        <category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
        <content type="application/xml">
            <m:properties>
                <d:ID m:type="Edm.Int32">5</d:ID> 
                <d:Name>Name5</d:Name> 
            </m:properties>
        </content>
    </entry>
    </feed>

Value of enum type is an integer. It is simple type which it is possible to transfer via service. Thus, we do small addition to this entity.

[DataServiceKey("ID")]
[IgnoreProperties("State")]
public class SampleEntity
{
    public int ID { get; set; }
 
    public string Name { get; set; }
 
    public int StateValue { get; set; }
 
    public StateEnum State
    {
        get { return (StateEnum)StateValue; }
        set { StateValue = (int)value; }
    }
}

After that, the service working with specified entity will ignore State property, but thus on the client will be transferred StateValue. It is easy to be convinced of it if to access to service through a browser.

<?xml version="1.0" encoding="utf-8" standalone="yes" ?> 
<feed xml:base="http://localhost:4321/WebDataService1.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
    <title type="text">Data</title> 
    <id>http://localhost:4321/WebDataService1.svc/Data</id> 
    <updated>2009-11-29T06:13:47Z</updated> 
    <link rel="self" title="Data" href="Data" /> 
    <entry>
        <id>http://localhost:4321/WebDataService1.svc/Data(1)</id> 
        <title type="text" /> 
        <updated>2009-11-29T06:13:47Z</updated> 
        <author>
        <name /> 
        </author>
        <link rel="edit" title="SampleEntity" href="Data(1)" /> 
        <category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
        <content type="application/xml">
            <m:properties>
                <d:ID m:type="Edm.Int32">1</d:ID> 
                <d:Name>Name1</d:Name> 
                <d:StateValue m:type="Edm.Int32">1</d:StateValue> 
            </m:properties>
        </content>
    </entry>
    <entry>
        <id>http://localhost:4321/WebDataService1.svc/Data(2)</id> 
        <title type="text" /> 
        <updated>2009-11-29T06:13:47Z</updated> 
        <author>
        <name /> 
        </author>
        <link rel="edit" title="SampleEntity" href="Data(2)" /> 
        <category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
        <content type="application/xml">
            <m:properties>
                <d:ID m:type="Edm.Int32">2</d:ID> 
                <d:Name>Name2</d:Name> 
                <d:StateValue m:type="Edm.Int32">2</d:StateValue> 
            </m:properties>
        </content>
    </entry>
    <entry>
        <id>http://localhost:4321/WebDataService1.svc/Data(3)</id> 
        <title type="text" /> 
        <updated>2009-11-29T06:13:47Z</updated> 
        <author>
        <name /> 
        </author>
        <link rel="edit" title="SampleEntity" href="Data(3)" /> 
        <category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
        <content type="application/xml">
            <m:properties>
                <d:ID m:type="Edm.Int32">3</d:ID> 
                <d:Name>Name3</d:Name> 
                <d:StateValue m:type="Edm.Int32">1</d:StateValue> 
            </m:properties>
        </content>
    </entry>
    <entry>
        <id>http://localhost:4321/WebDataService1.svc/Data(4)</id> 
        <title type="text" /> 
        <updated>2009-11-29T06:13:47Z</updated> 
        <author>
        <name /> 
        </author>
        <link rel="edit" title="SampleEntity" href="Data(4)" /> 
        <category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
        <content type="application/xml">
            <m:properties>
                <d:ID m:type="Edm.Int32">4</d:ID> 
                <d:Name>Name4</d:Name> 
                <d:StateValue m:type="Edm.Int32">1</d:StateValue> 
            </m:properties>
        </content>
    </entry>
    <entry>
        <id>http://localhost:4321/WebDataService1.svc/Data(5)</id> 
        <title type="text" /> 
        <updated>2009-11-29T06:13:47Z</updated> 
        <author>
        <name /> 
        </author>
        <link rel="edit" title="SampleEntity" href="Data(5)" /> 
        <category term="WebApplication69.SampleEntity" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /> 
        <content type="application/xml">
            <m:properties>
                <d:ID m:type="Edm.Int32">5</d:ID> 
                <d:Name>Name5</d:Name> 
                <d:StateValue m:type="Edm.Int32">1</d:StateValue> 
            </m:properties>
        </content>
    </entry>
</feed>

The last, that it is necessary to make is to inform client library on, how to use similar fields. For this purpose on the client side we declare the necessary enum type, in a partial class we will add the necessary property and we will specify IgnoreProperties attribute.

public enum StateEnum
{
    Normal = 1,
    Error = 2
}
 
[IgnoreProperties("State")]
public partial class SampleEntity
{
    public StateEnum State
    {
        get { return (StateEnum)StateValue; }
        set { StateValue = (int)value; }
    }
}

Now at the client side it is possible to access to the necessary property and to receive value of enum type.

class Program
{
    static void Main(string[] args)
    {
        var context = new MyDataContext(new Uri(@"http://localhost:4321/WebDataService1.svc/"));
        foreach (var entity in context.Data)
        {
            Console.WriteLine(entity.State);
        }
        Console.Read();
    }
}

 

Certainly, the presented decision does not pretend to be the elegant decision, but can be usable in some cases.

Source:

ADO.NET Data Services 1.5: server driven paging.

We continue to consider new possibilities of ADO.NET Data Services 1.5 and today we will look possibility of compulsory breakdown of data into pages.

Possibility of breakdown of data on pages already was present at first version of Astoria. For these purposes it was possible to construct query by means of Take/Skip operators. Changing values of these parametres it was possible to get paginal access to data from the client. Nevertheless, at the access to a collection without parametres service returned completely all collection. The described behaviour seems quite logical, but it not always is desirable. For example, if in a collection the considerable quantity of objects the acceess to such collection will by all means entail the raised loading on a server contains. Therefore in version 1.5 the decision on addition of possibility of compulsory breakdown on pages was accepted.

To enable of the described possibility it is necessary to define additional behaviour in configuration of service. In particular SetEntitySetPageSize method which allows to define the size of page for each collection is necessary for us.

public class WebDataService : DataService<NorthwindEntities>
{
    public static void InitializeService(DataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("*", EntitySetRights.All);
    
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        config.SetEntitySetPageSize("Categories", 5);
    }
}

In case of described above service, at the access to Categories collection data will be broken into pages on five objects.

Server Driven Paging

Apparently, for the access to the following page it is necessary to use a $skiptoken keyword. In this case URI format will look as follows:

http://.../WebDataService.svc/Categories?$skiptoken=5

The given functionality also is supported and in a client proxy. At the usual access to a collection the specified number of objects will be given out the client only. For the access to other pages it is necessary to use Skip() method.

var client = new NorthwindEntities(new Uri(@"..."));
var q = from c in client.Categories.Skip(2)
        select c;
 
foreach (var item in q)
{
    // ..
}
ADO.NET Data Services 1.5: projections.

Recently I’ve started discussion about ADO.NET Data Services 1.5. I spoke about main trends in this project. Now I want to say about some details. Here we will speak about possibilities to create projections of data in version 1.5 of ADO.NET Data Services.

Necessity of creation of projections was present at first version of Astoria. However, as we know, time and resources are limited, therefore such possibility has appeared only in version 1.5. Possibility of creation of projections is necessary in those situations when an entity, containing in collections on service contain a considerable quantity of fields, and some fields are necessary to the client only. In this case the client is compelled to load all fields of these objects and by that to generate the superfluous traffic and increasing time of performance of queries.

In version 1.0 it was offered to solve a problem by division of the big entity on a little bit small and to work with them separately. Certainly, such approach creates many problems. For example, in such situation it is required to make additional efforts in case of editing of such collections. Besides, the quantity of collections of data on service can essentially increase. In this case the logical decision arises - to ask for service to return not all fields of objects, but only what it is necessary directly in URI.

The idea of work of the mechanism of projections consists in it in ADO.NET Data Services 1.5. Every time when it is necessary to return a specific set of fields, we set it obviously in URI. Thus other fields are ignored and not transferred to the client.

For execute of similar query there was a new "select" keyword. For example, if it is necessary to select two fields ProductName and UnitPrice it is necessary to execute the following query:

http://../WebDataService.svc/Products()?$select=ProductName,UnitPrice

Similarly, if it is necessary to select all fields, having ignored this operator or having specified as value "*":

http://../WebDataService.svc/Products()?$select=*

In some situations possibility of creation of projections can be undesirable. In this case it can be switch off, using additional parametres in service configuration. For this purpose in DataServiceConfiguration class there was property DataServiceBehavior which allows to adjust behaviour of service. In this case we are interested in AcceptProjectionRequests property.

public class WebDataService : DataService<NorthwindEntities>
{
    public static void InitializeService(DataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("*", EntitySetRights.All);
 
        config.DataServiceBehavior.AcceptProjectionRequests = true;
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
    }
}

At use of a client proxy possibility of creation of projections also can be used conveniently. For this purpose it is necessary to construct LINQ-query where in Select section to specify necessary fields.

var client = new NorthwindEntities(new Uri(@"http://.../WebDataService.svc/"));
var q = from c in client.Categories
        select new { c.CategoryName, c.Description };

This functionality was very necessary in first version ADO.NET Data Services and now it was is added. And now we can use services even more effectively.

Displaying of progress of downloading data in WCF services

Platform Windows Communication Foundation can be used not only for a simple operations call, but also for transfer of big parts of data (for example, files in some mbyte). Sometimes such scenarios are applicable and on slow channels. In this case an indicator of executing of operation (progress bar) is necessary.

For simplicity we will use BasicHttpBinding binding. The key moment at implementation of the given scenario is setting of TransferMode parameter to Streamed value. Thus, data will be transferred as a stream.

After that we will define the contract. It is required to transfer a file name, its size and contents to the client side.

[ServiceContract]
public interface IFileTransferService
{
    [OperationContract]
    RemoteFileInfo DownloadFile(DownloadRequest request);
}
 
[MessageContract]
public class DownloadRequest
{
    [MessageBodyMember]
    public string FileName;
}
 
[MessageContract]
public class RemoteFileInfo : IDisposable
{
    [MessageHeader(MustUnderstand = true)]
    public string FileName;
 
    [MessageHeader(MustUnderstand = true)]
    public long Length;
 
    [MessageBodyMember(Order = 1)]
    public Stream FileByteStream;
 
    public void Dispose()
    {
        if (FileByteStream != null)
        {
            FileByteStream.Close();
            FileByteStream = null;
        }
    }
}

Apparently, DownloadFile operation returns RemoteFileInfo object which contains the necessary information.

public class FileTransferService : IFileTransferService
{
    public RemoteFileInfo DownloadFile(DownloadRequest request)
    {
        var filePath = request.FileName;
        var fileInfo = new FileInfo(filePath);
 
        if (fileInfo.Exists==false)
        {
            throw new FileNotFoundException("File not found", request.FileName);
        }
 
        var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
 
        var result = new RemoteFileInfo
                         {
                             FileName = request.FileName, 
                            Length = fileInfo.Length, 
                            FileByteStream = stream
                         };
 
        return result;
    }
}

Now it is necessary to host service

class Program
{
    static void Main()
    {
        var myServiceHost = new ServiceHost(typeof(FileService.FileTransferService));
        myServiceHost.Open();
 
        Console.ReadKey();
 
        myServiceHost.Close();
    }
}

Thus the configuration file will have the following data.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="FileTransferServicesBinding" transferMode="Streamed" messageEncoding="Mtom" maxReceivedMessageSize="20134217728" />
            </basicHttpBinding>
        </bindings>
        <services>
            <service behaviorConfiguration="MyServiceTypeBehaviors" name="FileService.FileTransferService">
                <endpoint address="getfile"
                  binding="basicHttpBinding"
                  bindingConfiguration="FileTransferServicesBinding"
                  contract="FileService.IFileTransferService" />
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost/" />
                    </baseAddresses>
                </host>
            </service>
        </services>
        <behaviors>
            <serviceBehaviors>
                <behavior name="MyServiceTypeBehaviors">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
    </system.serviceModel>
</configuration>

Now it is necessary to create a client side.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="fileBinding" maxReceivedMessageSize="20134217728" messageEncoding="Mtom" transferMode="Streamed" />
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost/getfile"
                                binding="basicHttpBinding"
                                bindingConfiguration="fileBinding"
                                contract="Client.FileTransferClient.IFileTransferService" />
        </client>
    </system.serviceModel>
</configuration>

After generation of a client proxy it looks as follows.

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class FileTransferServiceClient : 
    System.ServiceModel.ClientBase<Client.FileTransferClient.IFileTransferService>, 
    Client.FileTransferClient.IFileTransferService
{
   public FileTransferServiceClient()
   {
   }
   
   public FileTransferServiceClient(string endpointConfigurationName) : 
           base(endpointConfigurationName)
   {
   }
   
   public FileTransferServiceClient(string endpointConfigurationName, string remoteAddress) : 
           base(endpointConfigurationName, remoteAddress)
   {
   }
   
   public FileTransferServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
           base(endpointConfigurationName, remoteAddress)
   {
   }
   
   public FileTransferServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
           base(binding, remoteAddress)
   {
   }
   
   Client.FileTransferClient.RemoteFileInfo Client.FileTransferClient.IFileTransferService.DownloadFile(Client.FileTransferClient.DownloadRequest request)
   {
       return base.Channel.DownloadFile(request);
   }
}

Let's create more convenient DownloadFile method.

public long DownloadFile(ref string fileName, out System.IO.Stream fileByteStream)
{
    Client.FileTransferClient.DownloadRequest inValue = new Client.FileTransferClient.DownloadRequest();
    inValue.FileName = FileName;
    Client.FileTransferClient.RemoteFileInfo retVal = ((Client.FileTransferClient.IFileTransferService)(this)).DownloadFile(inValue);
    FileName = retVal.FileName;
    FileByteStream = retVal.FileByteStream;
    return retVal.Length;
}

Now we should receive this stream and read out from it the information in the portions.

var client = new FileTransferClient.FileTransferServiceClient();
 
Stream inputStream;
long length = client.DownloadFile(ref fileName, out inputStream);
 
using (var writeStream = new FileStream(fileName, FileMode.CreateNew, FileAccess.Write))
{
    const int bufferSize = 2048;
    var buffer = new byte[bufferSize];
 
    do
    {
        int bytesRead = inputStream.Read(buffer, 0, bufferSize);
        if (bytesRead == 0)
        {
            break;
        }
 
        writeStream.Write(buffer, 0, bytesRead);
 
        progressBar1.Value = (int)(writeStream.Position * 100 / length);
    }
    while (true);
 
    writeStream.Close();
}
 
inputStream.Dispose();
client.Close();

Great! Now we have received the application which will display progress of downloading data on the client. Similarly it is possible to make uploading data to a server. If this infomation is interesting to you I recommend to read more detailed article.

Source code:

Throttling in WCF

Here I want to give the main information which need to be known at setting of the service working with high load.

ConcurrencyMode

Parameter which defines a service operating mode - how many real threads will process messages and to execute actions. This parameter can have following values:

  • Single – Messages are processed sequentially in a single thread (default value).
  • Reentrant – Similarly Single with some singularity (see MSDN).
  • Multiple – Messages are processed in parallel in several threads.

MaxConcurrentCalls parameter which limits a maximum quantity of threads of processing of competing calls is refered with this parameter. Usually ConcurrencyMode parameter is set at service definition.

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Service1 : IService1
{
    public string GetData(int value)
    {
        return string.Format("You entered: {0}", value);
    }
 
    public CompositeType GetDataUsingDataContract(CompositeType composite)
    {
        if (composite.BoolValue)
        {
            composite.StringValue += "Suffix";
        }
        return composite;
    }
}
InstanceContextMode

Very important parameter which defines in what way is created object on the service side for query processing. The parameter can have following values:

  • PerCall – Creates a new instance of service object on each call (default value).
  • PerSession – Creates a new instance of service object on each session.
  • Single – Creates the single instance of service object which will proceed all queries.

It is clear that more effectively to use Single mode. In this case the single object of service will be created and it is not necessary to care of use of memory and other resources. However, in cases when service contains a state to use mode Single it is impossible. In this case it is possible to limit quantity of simultaneously existing instances of service in MaxConcurrentInstances parameter. Also it is possible to limit quantity of simultaneously working sessions, it becomes by means of MaxConcurrentSessions parameter.

Usually InstanceContextMode parameter is set at service definition.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Service1 : IService1
{
    public string GetData(int value)
    {
        return string.Format("You entered: {0}", value);
    }
 
    public CompositeType GetDataUsingDataContract(CompositeType composite)
    {
        if (composite.BoolValue)
        {
            composite.StringValue += "Suffix";
        }
        return composite;
    }
}

 

Besides, on properties of stability of the application on external attacks a quotas can depends various parameters. For example, sendTimeout, receiveTimeout, maxReceivedMessageSize etc. More information about it you can read at MSDN.

ADO.NET Data Services – what waits for us in the future

ADO.NET Data ServicesApproximately hardly there is more than year back we have seen a new services platform - ADO.NET Data Services. Its occurrence has marked the beginning of wide use of the REST-approach by many developers. At that time this platform was represented as the convenient tool for access to data through HTTP.

Lately it is possible to understand, that this tool is really successful - huge number of developers have started to use immediately it in the projects. The reason for it is quite logical - use of ADO.NET Data Services allows to cut down expenses on realisation of the most typical scenarios at work with services. It does not mean that SOAP-services and WCF have left in the past, however, in scenarios of the data access preference began to give to ADO.NET Data Services.

In spite of the fact that this platform had some defects at work in non-standard situations, its realisation was enough successful. Therefore among developers there could be a wrong impression that development of ADO.NET Data Services has stopped. It is wrong. Here I will tell that we should see in new versions of this product.

As is known in RTM status now is ADO.NET Data Services 1.0. Subsequently in plans there is a release of version 1.5 which will be a part of .NET 4.0 and Visual Studio 2010. At present version 1.5 is in CTP2 state.

That is interesting, the further direction of development of the project got out proceeding from comments which went from developers community. Thus, version 1.5 will be focused on closer integration with WPF/Silverlight applications, will expand possibilities on executing of server queries and will allow to use even more conveniently services at the client side.

New possibilities of ADO.NET Data Services 1.5 it is much more and we will discuss them with you in the near future. And now I wish to make the small review of that we should see in the new version.

  • One of weak places of ADO.NET Data Services at present is that in some scenarios we are compelled to load superfluous quantity of data on the client. For example, if the entity contains 40 fields at the access to a corresponding collection we are compelled to load 40 fields all these. At present for such situations it is offered to split entity into smaller and to work with them separately, and for the main query to generate representation with association. However, all it creates additional problems by working out. Other even more unpleasant problem is in case of need to receive quantity of objects in a collection we are compelled to load all collection entirely and already on the client to consider quantity of objects. In new version of ADO.NET Data Services the special attention is paid to these problems. Now we can query projections of any data, and not just entirely all entity. There was a new operator $count which will allow to receive quantity of entities in a collection.
  • As for an application programming even more often use platforms WPF and Silverlight in new version ADO.NET Data Services the special attention is paid to data binding. This mechanism is successfully enough applied in WPF/Silverlight projects and declarative binding with data became already habitual approach to working out. In the new version all entities which are generated on the client will implement INotifyPropertyChanged interface, thanks to what begins possible to carry out declarative binding with service data.
  • Also in the new version of a considered platform the attention is paid to work with binary large objects (BLOB), for example, with images. Also fields will be allocated in a special way in metadata and to be loaded on the client side only if necessary.
  • Interaction with other platforms. In spite of the fact that services ADO.NET Data Services are based on open standards, for work with these services, for example, from Java it is necessary to parse answers from service and to generate queries manually. For simplification of this problem within version 1.5 the mechanism of change of appearance of the answer is implemented (feed customization). Besides, client libraries for work with services ADO.NET Data Services, for example, PHP Toolkit for ADO.NET Data Services which we certainly also will consider already have started to appear.

Thus, the general tendencies and directions are visible to where project ADO.NET Data Services moves and that we should expect from it in the near future.

In the near future we will talk in more details about each of possibilities of ADO.NET Data Services v.1.5, and now I wish to wish you successes in construction of your distributed applications!

ADO.NET Data Services v.1.5 CTP2

Astoria team has released next CTP of ADO.NET Data Services 1.5. In comparison with previous release, CTP2 is really big work and we can observe now already that ADO.NET Data Services becomes even more powerful platform. As a whole it is visible, that development of Astoria is directed on more closer integration with Silverlight and .NET Framework 3.5 SP1.

What’s new in CTP2:

  • Projection. It is new feature for Astoria which has appeared only in this CTP. This feature allows to build more difficult projections using ADO.NET Data Services, and is accessible both server functionality, and client.
  • Data Binding. Feature of binding with the user interface in WPF and Silverlight already was in previous CTP, however in new release here has occurred small refactoring and binding began to do even easier.
  • Row count. Has changed nothing, bugs has been fixed.
  • Feed customization. The quantity of elements which can be adjusted is expanded.
  • Server driven paging. Support in client library is added.
  • Enhanced LOB Support. Support in client library is added.
  • Request Pipeline. Now it is possible to handle something in a chain of processing of request using model of events (something similar on model of events ASP.NET). It is necessary for even big possibilities of expansion of functionality of services.
  • New “Service Provider” interface. Refactoring has been executed.

It is besides, informed, that has been fixed a number of errors. Thus, release of ADO.NET Data Services v.1.5 on one CTP became nearly.

Also there was an information that all these possibilities of version 1.5 will be a part.NET Framework 4.

Source: http://blogs.msdn.com/astoriateam/archive/2009/08/31/ado-net-data-services-v1-5-ctp2-now-available-for-download.aspx

PHP Toolkit for ADO.NET Data Services – erasing bounds of technologies: PHP + .NET

Microsoft Interoperability team announced an release of the new project which is the bridge between PHP and.NET and erases bounds of technologies even more. This project allows developers on PHP even more easier to access and use all power of .NET  services which based on ADO.NET Data Services.

From the point of view of working out the scheme looks classically enough. By working out it is necessary to use utility PHPDataSvcUtil which is in PHP Toolkit for ADO.NET Data Services. This utility will generate proxies-classes on PHP using metadata which are accessible to service on the basis of ADO.NET Data Services. After that on PHP also it will be necessary to connect libraries PHP Toolkit to the project for ADO.NET Data Services. Further, after all these simple actions it will be possible to use all power of ADO.NET Data Services platform within of appendices on PHP in more convenient way.

Let's look how the code on platform PHP for executing of queries to ADO.NET Data Services will look. Firstly it is necessary to connect a file with proxies-classes, which generated by PHPDataSvcUtil utility:

<?PHP
    require_once 'NorthwindClient.php';
    define("SERVICE_URI", "http://localhost:8080/Northwind.svc");
?>

After that it is possible to create the objects of a class which implements the logic of the client and to carry out queries to remote service. Unfortunately, here we cannot take advantage of LINQ syntax for construction of queries to service. Therefore it is necessary to write query manually in the form of URI.

<?PHP
    $client = new NorthwindEntities(SERVICE_URI);
    $query = $client->ExecuteQuery("Customers?\$filter=Country eq 'UK'");
?>

Now, after successful designing of query it is possible to access for a data and to show result to the user:

<?PHP
    foreach($query as $customer)
    {
        echo "<p>";
        echo $customer->CustomerID;
        echo "<br/>";
        echo $customer->CompanyName;
        echo "</p>";
    }
?>

Here it is well visible, that we access to strongly typified objects, and result we receive in the form of objective collections. Such way is very similar to how we work with services of ADO.NET Data Services within  the .NET-client. These of entity classes also have been generated by utility PHPDataSvcUtil.

Pablo Castro (program manager, ADO.NET Data Services) and Claudio Caldato (program manager, interoperability, techincal strategy team) have made the small review of this library on Channel 9 in which they tell more details

At last that the project is the project with an open source code is very interesting and is accessible on CodePlex. Besides, the project is developed by company Persistent Systems, but fund by Microsoft.

Links:

  1. The announcement in a blog of Astoria team - http://blogs.msdn.com/astoriateam/archive/2009/08/21/announcing-the-php-toolkit-for-ado-net-data-services.aspx
  2. The description in a blog of Interoperability team - http://blogs.msdn.com/interoperability/archive/2009/08/21/a-new-bridge-for-php-developers-to-net-through-rest-php-toolkit-for-ado-net-data-services.aspx
  3. Channel9 - http://channel9.msdn.com/posts/jccim/Consuming-data-over-the-web-between-PHP-and-NET-with-REST-and-ADONET-Data-Services/
  4. The project at CodePlex - http://phpdataservices.codeplex.com/
Windows Marketplace for Windows Mobile users

Marat Bakirov already wrote in his blog about Windows Marketplact for Mobile users. Till now over Windows Marketplace the curtain of secret kept and it was not clear as this direction will develop. And here recently, at WPC some details Windows Marketplace for mobile devices became known.

Some facts about Windows Marketplace for Windows Mobile users (some of them already have been sounded earlier):

  • For application placing on Windows Marketplace it is required to pay $99 per year. Thus it will be possible to place five applications. For each additional application it is required to pay $99 per a year.
  • The developer will receive 70% from application cost. 30% will leave in favour of Windows Marketplace.
  • Before placing in Windows Marketplace all application should pass certification.
  • The applications placed in Windows Marketplace can be bought conveniently and safely directly from the mobile device. Application for Windows Marketplace will be accessible to these purposes in Windows Mobile 6.5 out of the box, and for versions 6.0 and 6.1 it it will be possible to install in addition in the end of 2009.
  • On 27th of July, 2009 Windows Marketplace it will be accessible to a wide range of users and developers. Subsequently applications from Windows Marketplace can be downloaded from 30 million mobile devices worldwide. The list of the countries in which works Windows Marketplace:
    • Australia
    • Austria
    • Belgium
    • Brazil
    • Canada
    • Denmark
    • Finland
    • France
    • Germany
    • Greece
    • Hong Kong SAR
    • India
    • Ireland
    • Italy
    • Japan
    • Luxembourg
    • Mexico
    • New Zealand
    • Netherlands
    • Norway
    • Poland
    • Portugal
    • Singapore
    • Spain
    • Sweden
    • Switzerland
    • Taiwan
    • United Kingdom
    • United States

What does it mean for us, developers? It means, that in the near future there will be a platform which for small money will allow to place easily and simply our applications in the global market and to earn on it.

References:

Windows 7 Sensor and Location platform: Implementation of own sensor (Part 3/3)

Recently I have told about use Sensor and Location platform in the applications. We have seen, that use of this component set can be very convenient for the application and do not demand many efforts. Also we have an opportunity to work with set of devices in the unified style. Problem of use of this platform there is a presence of drivers for Windows 7 and presence of wrappers for Sensor API. Development of the driver for the device - a task of the manufacturer. And implementation of support in Sensor API can be made own forces.

As I already spoke an entry point is SensorManager class . By means of this class it is possible to get access to the necessary sensor controls and to work with them. This class has methods of getting of the list of all sensors, sensor getting by ID or on type, request to sensor use, and also event of change of quantity of sensors in system.

SensorManager

 

Each sensor has two main types of identifiers - SensorId and TypeId. TypeId identifies a separate class of devices. For example, by it it is possible to get all sensors of light in system, or any other types of devices. SensorId it is given it is unique to each device. For example, if in system three same sensors of movements everyone will have the unique identifier. Is also CategoryId which unites sensors in a category.

Each identifier represents GUID. They are set by manufacturers by developing of the device and drivers. Thus, it is possible to get a concrete sensor only knowing it ID. Each sensor is presented by Sensor class. It has the general information about a sensor and methods which data from the generalised collections in not typified kind allow to obtain. It is clear, that such data presentation is not so convenient for our applications. Therefore for each sensor it is accepted to implement a class-wrapper within Sensor API. It is implemented by inheritance from general class Sensor. In demonstration examples already there are two such realisations - for 3D accelerometer and for light sensor. However, at the device which we considered earlier there are also touch buttons which also can be used. Therefore let's implement such class for this sensor.

We will define a new class which will be the inheritor of Sensor class. That it was recognised in Sensor API it it is necessary to mark with SensorDescription attribute in which to specify TypeId for this type of sensors. In base class Sensor there are two important things for us - DataReport property and DataReportChanged event. This property contains data from a sensor, and event fires at their change. The task of our class - to take advantage of these data and to deliver to their user of our class in a convenient kind. For this purpose we will create one more small class which will be engaged in analysis of the information from DataReport.

Experimental by we will find out, that by pressing of the button 1 the code 1 is generated, by pressing 2 - the code 2 is generated, by pressing 3 - the code 4 is generated, and by pressing 4 - the code 8 is generated. It is visible, that binary bits here are used. Also the code 0 in a case unpress of all buttons is generated. Thus, we can write the following code.

[SensorDescription("545C8BA5-B143-4545-868F-CA7FD986B4F6")]
public class SwitchArraySensor : Sensor
{
    public class SwitchArraySensorData
    {
        private static Guid KeyStateProperyId = new Guid(@"38564a7c-f2f2-49bb-9b2b-ba60f66a58df");
 
        public SwitchArraySensorData(SensorReport report)
        {
            uint state = (uint) report.Values[KeyStateProperyId][0];
            Button1Pressed = (state & 0x01) != 0;
            Button2Pressed = (state & 0x02) != 0;
            Button3Pressed = (state & 0x04) != 0;
            Button4Pressed = (state & 0x08) != 0;
        }
 
        public bool Button1Pressed { get; private set; }
        public bool Button2Pressed { get; private set; }
        public bool Button3Pressed { get; private set; }
        public bool Button4Pressed { get; private set; }
    }
 
    public SwitchArraySensorData Current
    {
        get { return new SwitchArraySensorData(DataReport); }
    }
 
    public event EventHandler StateChanged;
 
    public SwitchArraySensor()
    {
        DataReportChanged += SwitchArraySensor_DataReportChanged;
    }
 
    void SwitchArraySensor_DataReportChanged(Sensor sender, EventArgs e)
    {
        if (StateChanged != null)
        {
            StateChanged.Invoke(sender, e);
        }
    }
}

 

Actually, this class is a wrapper in Sensor API for the sensor necessary to us. For its use I should subscribe for StateChanged event and receive the information through Current property.

For getting of the list of accessible sensor of the some type it is possible to use GetSensorsByTypeId method of SensorManager class. Thus TypeId these sensor it will be defined on the basis of set SensorDescription attribute. Now, using these sensors we can subscribe on necessary event and obtain data in a kind convenient for the application. For example, we can display on the form a state of pressing of buttons.

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    var sensors = SensorManager.GetSensorsByTypeId<SwitchArraySensor>();
    foreach (SwitchArraySensor sensor in sensors)
    {
        switch (sensor.FriendlyName)
        {
            case "Left Switch Array Sensor":
                sensor.StateChanged += delegate(object leftSensor, EventArgs arg)
                {
                    var buttons = ((SwitchArraySensor)leftSensor).Current;
                    SwitchState(LeftButton1, buttons.Button1Pressed);
                    SwitchState(LeftButton2, buttons.Button2Pressed);
                    SwitchState(LeftButton3, buttons.Button3Pressed);
                    SwitchState(LeftButton4, buttons.Button4Pressed);
                };
                break;
            case "Right Switch Array Sensor":
                sensor.StateChanged += delegate(object rightSensor, EventArgs arg)
                {
                    var buttons = ((SwitchArraySensor)rightSensor).Current;
                    SwitchState(RightButton1, buttons.Button1Pressed);
                    SwitchState(RightButton2, buttons.Button2Pressed);
                    SwitchState(RightButton3, buttons.Button3Pressed);
                    SwitchState(RightButton4, buttons.Button4Pressed);
                };
                break;
        }
 
    }
}

 

As a result we will receive the application which looks as follows.

Certainly, an example with realisation of a similar sensor synthetic enough. However, it obviously shows process of connection of the sensor to Sensor API.

I wish successes to you in creation of your context-aware applications!

Sample application:

More Posts Next page »