Archive

Author Archive

How to enable Intellisense for CodeFluent Entities runtime configuration?

September 16, 2014 Leave a comment

CodeFluent Entities generated code can be configured using the application configuration file (App.config or web.config):

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="Sample"
     type="CodeFluent.Runtime.CodeFluentConfigurationSectionHandler,
           CodeFluent.Runtime" />
  </configSections>
  <Sample connectionString="<connection string>" useDateTime2="true" />
</configuration>

The configuration section is describe in the documentation: http://www.softfluent.com/documentation/BOM_ApplicationConfiguration.html.

This section is not known by Visual Studio, so you may have the following message:

ErrorXML

In fact Visual Studio doesn’t have an XML schema for this section and so it can’t validate it. At the same time we cannot provide a generic schema as the section name is Project specific. So the solution is to use The Template producer  which will generate the XML  schema based on the information from your Project.

  1.  

  2. Add a template producer

     

  3. Build the model
  4. Open the app.config or web.config file and add the following xml attributes (replace <Default namespace> by your project default namespace)

<configuration

xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221;

xsi:schemaLocation=”http://www.softfluent.com/<Default Namespace>/CodeFluentConfiguration.xsd CodeFluentConfiguration.xsd”>

You should now have auto-completion of the CodeFluent Entities configuration section.

binary services

 

 

 

 

 

 

 

Note: this xml schema includes only most common settings. If you think we forgot some useful settings, please leave a comment.

Happy configuration,

The R&D Team

Localize Dynamic Resources using an Aspect

September 15, 2014 Leave a comment

CodeFluent Entities handles static localization with the message concept. Static resources refer to all those UI messages that will never change throughout your application’s life-time: labels, error messages, information messages, titles, button texts, tool tips, etc.

CodeFluent Entities (Personal and Ultimate Edition) also handles dynamic localization out of the box. Dynamic resources refer to localized data created at runtime. For instance a web shop could have an international catalog in several languages, and this catalog should be displayed in a specific language depending on the users’ language (i.e. culture in .Net). Administrators add, remove or modify items from this catalog during the application’s life-time. Thus, administrators of the catalog will need to create catalog items with labels in several languages in order to support internationalization.

Let’s see how to use dynamic localization with CodeFluent Entities.

First, create an entity:

Then add the localization aspect:

Now we have to indicate the Description property is localizable:

That’s all. Yes you read that right! As a bonus you can define localized instances in the model:

Let’s generate the code and see what is generated:

The database contains two tables

The product table contains non-localized columns and the default value of the localized columns. The default value is used when no translation exists for one culture while loading row.

The table “ProductLocalized” contains translations:

The BOM is edited automatically but you can use it the same way as if there is no dynamic localization. Save and Load method use Thread.CurrentUICulture to know which description to load or save.

// First we create a product with an English description
Thread.CurrentThread.CurrentUICulture = new CultureInfo(1033);
Product product = new Product();
product.Name = "Sample product";
product.Description = "A description in English";
product.Save();

// We create a French description.
Thread.CurrentThread.CurrentUICulture = new CultureInfo(1036);
product.Description = "Une description en français";
product.Save();

// We can also add localization by using the static method SaveLocalizedValues
Product.SaveLocalizedValues(product, 1033, isDefault: true, description: "A description in English");

// Load products with an English description
Thread.CurrentThread.CurrentUICulture = new CultureInfo(1033);
var productsEn = ProductCollection.LoadAll();

// Load products with a French description
Thread.CurrentThread.CurrentUICulture = new CultureInfo(1036);
var productsFr = ProductCollection.LoadAll();

// Load products with a German description =&gt; There is no German description so the default value is used
Thread.CurrentThread.CurrentUICulture = new CultureInfo(1031);
var productsDe = ProductCollection.LoadAll();

Localizing Dynamic Resources is very easy with CodeFluent Entities and the <a href="http://www.softfluent.com/documentation/BOM_LOC_DynamicResources.html">localization aspect</a>. Good news, this aspect is available out of the box!

Happy localizing,

The R&D Team

Categories: Aspects

Single Instance Application in .NET

September 10, 2014 Leave a comment

Running a single instance of an application is very easy with CodeFluent Runtime. Add the following nugget package: http://www.nuget.org/packages/CodeFluentRuntimeClient and use the SingleInstance class:

 
SingleInstance _singleInstance = new SingleInstance("Unique Name"); 

public MainForm() 
{ 

  if (!_singleInstance.WaitForMutext(IntPtr.Zero, IntPtr.Zero)) 
  { 
    Close(); 
  } 

  InitializeComponent();
}

If you want to make an action when the second instance is started, you can handle the windows message “”WM_” + uniqueName”:

 
protected override void WndProc(ref Message m) 
{ 
  if (m.Msg == _singleInstance.Message) 
  { 
    // your code
  } 
  base.WndProc(ref m); 
} 

SingleInstance class provides a helper to activate a Form, so when the second instance is started, it actually display the form of the first instance:

 
public partial class MainForm : Form 
{ 
  SingleInstance _singleInstance = new SingleInstance("My App"); 

  protected override void WndProc(ref Message m) 
  { 
  // Display the window of the first instance 
    _singleInstance.OnWndProc(this, m, true); 
    base.WndProc(ref m); 
  } 
} 

You can also force the instance to run, even if one is already running, by using the command line argument “/siForce” or “-siForce”.

 
$> myapp.exe /siForce 

Happy runtime exploration,

The R&D Team

CommonMark for C# using CodeFluent Runtime

September 5, 2014 Leave a comment

Markdown is a plain text language that can be converted to HTML. This language is well adopted: GitHub, StackOverflow, Reddit, some blogging platforms, and many others.

This language had no specification, so there were many different implementations. A few days ago, Standard Markdown, quickly renamed to Common Markdown, was born. This is the first specification of Markdown. At the same time, the C and JavaScript implementation was released:

At SoftFluent we though JavaScript is great but we are mostly using C# so there is no Common Markdown implementation.

We’re not providing a C# implementation as it would take time to develop and to maintain. Here, we want to show you how to call JavaScript code from C# using the CodeFluent Script Engine from the CodeFluent Runtime.

This is just a sample/preview and not aims to be used in production.

The full (but very short) code is available on GitHub: https://github.com/SoftFluent/SoftFluent.CommonMarkdown 

Here’s the main code:

private static readonly string _language = DetermineBestEngine();
private static string DetermineBestEngine()
{
    // use IE9+'s chakra engine?
    bool useChakra = ScriptEngine.GetVersion(ScriptEngine.ChakraClsid) != null;
    return useChakra ? ScriptEngine.ChakraClsid : ScriptEngine.JavaScriptLanguage;
}
string method = @"
    function markdownToHtml(text) {
        var reader = new stmd.DocParser();
        var writer = new stmd.HtmlRenderer();
        var parsed = reader.parse(text);
        return writer.render(parsed);
    };";

using (ScriptEngine engine = new ScriptEngine(_language))
using (ParsedScript parsed = engine.Parse(File.ReadAllText("stdm.js") + method))
    return (string)parsed.CallMethod("markdownToHtml", engine.Eval(EncodeJavaScriptString(text)));

And how to use it:

Markdown.ToHtml(@"# Hello there
This is a paragraph.
- one
- two
- three
- four
1. pirate
2. ninja
3. zombie")

This code gives the following result :

<h1>Hello there</h1>
<p>This is a paragraph.</p>
<ul>
  <li>one</li>
  <li>two</li>
  <li>three</li>
  <li>four</li>
</ul>
<ol>
  <li>pirate</li>
  <li>ninja</li>
  <li>zombie</li>
</ol>

CodeFluent Runtime Client is free and available from NuGet. This package contains lots of useful class such as the ScriptEngine.

Have fun with Markdown,

The R&D Team

CodeFluent Runtime Database

August 28, 2014 Leave a comment

CodeFluent Entities comes with lots of useful DLL. Of course you all know CodeFluent.Runtime.dll or CodeFluent.Runtime.Web.dll. Today we’ll have a look at CodeFluent.Runtime.Database.dll.

The Runtime.Database DLL contains code to explore databases (schema, tables, views, columns, primary keys, constraints, stored procedures, and data). Currently, it supports:

  • SQL Server,
  • Oracle,
  • MySQL,
  • PostgreSQL,
  • SqlLite,
  • Sql Server CE
  • Access,
  • OleDb,
  • Xmi,
  • EnterpriseArchitect

Let’s see an example:

CodeFluent.Runtime.Database.Management.Database database = new CodeFluent.Runtime.Database.Management.SqlServer.Database("Server=(local)\\SQL2014;Database=Sample;Trusted_Connection=True;");

foreach (var table in database.Tables)
{
    Console.WriteLine(table.FullName);

    foreach (var column in table.Columns)
    {
        Console.WriteLine("    {0} {1}", column.EscapedName, column.CodeFluentType.DataType);
    }

    Console.WriteLine("    PK ({0})", ConvertUtilities.ConcatenateCollection(table.PrimaryKey.Columns, "EscapedName", ", "));

    table.MaxRows = 10; // Read only 10 rows
    Console.WriteLine(DatabaseUtilities.Trace(table.Data));
}

The Database class provides a very great abstraction of the database structure. Whatever the DBMS you use, the code is the same. For example if you are using MySQL, just replace CodeFluent.Runtime.Database.Management.SqlServer.Database by CodeFluent.Runtime.MySQL.Management.Database (located in CodeFluent.Runtime.MySQL) and run the code!

The DLL also contains code to execute SQL queries or SQL scripts.

Moreover you’ll find some graphical components to create or edit connection strings (the ones used by CodeFluent Entities):

Happy exploring,

The R&D team

Store Int128 in a database

August 26, 2014 1 comment

As you may have seen in our previous posts (here and here), the type system of CodeFluent Entities is very powerful. Today we’ll see how to persist a custom type.

Let’s use the Int128 class: https://int128.codeplex.com/SourceControl/latest#SoftFluent.Int128/Int128.cs

You may notice that the class implements the IBinarySerialize interface which is natively handled by CodeFluent Entities. So by default the value will be stored in a column of type varbinary and serialized by using the IBinarySerialize interface. But the Int128 is as long as a Guid: 128bits, so it may be a better idea to store it in a column of type uniqueidentifier.

Let’s create an entity with a property of type SoftFluent.Int128, and dbType Guid:

<cf:entity name="Sample">
  <cf:property name="Id" key="true" />
  <cf:property name="GuidInt128" typeName="SoftFluent.Int128" dbType="Guid" />
</cf:entity>

Now the trick is to replace the generated code. The result code will be:

protected virtual bool BaseSave(bool force)
{
    // ...
    persistence.AddParameter("@GuidInt128", new System.Guid(this.GuidInt128.ToByteArray()), System.Guid.Empty);
    // ...
}

protected virtual void ReadRecord(System.Data.IDataReader reader, CodeFluent.Runtime.CodeFluentReloadOptions options)
{
    // ...

    this._guidInt128 = new SoftFluent.Int128(CodeFluentPersistence.GetReaderValue(reader, "GuidInt128", System.Guid.Empty));
    // ...
}

The BOM producer understands some custom attributes. Among them, three are useful in our case:

  • addParameterExpression=”<attribute value>”
  • addParameterMethodName=”<attribute value>”
  • readValueExpression=”<attribute value>”

The first one allows to define the code when adding the parameter (BaseSave method):

persistence.AddParameter("@GuidInt128", <attribute value>, System.Guid.Empty);

The second one allows to change the method AddParameter by something else:

persistence.<attribute value>("@GuidInt128", this.GuidInt128, System.Guid.Empty);

The third one allows to define the code when reading the value from the DataReader:

this._guidInt128 = <attribute value>;

One way to store value as Guid is to use the combination of addParameterExpression and readValueExpression:

<cf:property name="GuidInt128"
              typeName="SoftFluent.Int128"
              dbType="Guid"
              xmlns:cfom="http://www.softfluent.com/codefluent/producers.model/2005/1"
              cfom:readValueExpression="new SoftFluent.Int128(CodeFluentPersistence.GetReaderValue(reader, &quot;GuidInt128&quot;, System.Guid.Empty))"
              cfom:addParameterExpression="persistence.AddParameter(&quot;@GuidInt128&quot;, new System.Guid(this.GuidInt128.ToByteArray()), System.Guid.Empty)" />

The second way to store value as Guid is to use addParameterMethodName and readValueExpression and to write an extension method:

<cf:property name="GuidInt128"
              xmlns:cfom="http://www.softfluent.com/codefluent/producers.model/2005/1"
              cfom:readValueExpression="new SoftFluent.Int128(CodeFluentPersistence.GetReaderValue(reader, &quot;GuidInt128&quot;, System.Guid.Empty))"
              cfom:addParameterMethodName="AddParameter"
              typeName="SoftFluent.Int128"
              dbType="Guid" />

And:

public static class PersistenceUtilities
{
    public static void AddParameter(this CodeFluentPersistence persistence, string name, Int128 value, Type type, PersistenceSerializationMode mode)
    {
        persistence.AddParameter(name, new Guid(value.ToByteArray()), Guid.Empty);
    }
}

This way the AddParameter will use the extension method.

When you have more than one custom property you may want to write an aspect to automate this process.

Thanks to the power of CodeFluent Entities, we have a column of type Guid and a property of type Int128, and all of this without extra code such as adding one unneeded property to convert value from Int128 to Guid.

Happy storing,

The R&D Team

Extended Search Aspect

August 20, 2014 1 comment

This aspect requires CodeFluent Entities build 774.

Third-party component providers such as Infragistics, Telerik or DevExpress, often provide data-grid with advanced filtering options:

CodeFluent Entities allows to generate Search methods by using CodeFluent Query Language (CFQL). For instance, searching for customers by name and date of birth can be done as so:

And the following method will be generated:

public static
 CustomerCollection Search(string fullName, System.DateTime dateOfBirth)

The function used to filter rows (Equals, Contains, StartsWith, etc.) is not dynamic: FullName will use the Equals or StartsWith functions depending of your configuration and DateOfBirth will use Equals function.

As its name implies, the extended search aspect extends these features. After registering the aspect in your project, you can configure the method to use dynamic filtering functions:

Now the generated method looks like:

public static CustomerCollection Search(
 string fullName, FilterFunctions fullNameFilterFunction,
 System.DateTime dateOfBirth, FilterFunctions dateOfBirthFilterFunction)

The aspect automatically create new parameters that allow to specify the function to use for each search parameter. FilterFunctions enumeration defines commonly used filters:

Here’s an example:

CustomerCollection.Search(
 "John", FilterFunctions.Contains,
 new DateTime(2014, 1, 1), FilterFunctions.IsLessThanOrEqualTo);

This enumeration can be multi-valued (optional). In this case you can combine functions, but the generated stored procedure is more complex so use it only when needed.

CustomerCollection.Search(
 "John", FilterFunctions.Contains | FilterFunctions.IsLessThan,
 new DateTime(2014, 1, 1), FilterFunctions.IsLessThanOrEqualTo);

You can also specify which functions should be supported:

Now we’re going to register the aspect in our solution. First, copy the SoftFluent.Samples.ExtendedSeach.Aspect project in your solution.

Then, add a reference in the model to the aspect project:

And select the ExtendedSearch aspect:

Finally, build your model! Search methods now have new parameters J.

With the power of CodeFluent Entities and a few lines of code, we have added the possibility to extend search method of our choice. Of course this aspect 100% reusable across all your projects. Can you do that without CodeFluent Entities?

The code is available on our GitHub repository: https://github.com/SoftFluent/CodeFluent-Entities/tree/master/Extensions/SoftFluent.ExtendedSearch

Happy coding,

The R&D Team

Categories: Aspects Tags: , ,
Follow

Get every new post delivered to your Inbox.

Join 51 other followers