Archive

Author Archive

CodeFluent Entities vs Entity Framework: Cascade save

April 15, 2015 Leave a comment

To avoid handling every relations in your data model, you may want to ask your access layer to synchronize update operations across related entities.

Entity Framework

With Entity Framework you will not have any feature available to automate a cascade save treatment. This Framework only offers you the way to save entities in your entire context. This is not really a cascading operation as it can be with the SQL Server “cascade delete” but it can do the tricks.

CodeFluent Entities

With CodeFluent Entities you can add a relation:

Then, you can configure the « save » cascading operations:

 

Cascade Save

 

Unlike the Cascade Delete feature which modify the generated stored procedure, it will only change the C# code:

public partial class Client : // ... 
    {

        public virtual bool Save()
        {
            if ((this._orders != null))
            {
                this.Orders.SaveAll();
            }
            bool localSave = this.BaseSave(false);
            return localSave;
        }

        // ...
    }

Simple and clean!

Conclusion

Entity Framework doesn’t include a cascade save feature.

CodeFluent Entities asks you for every relation  to configure an optional operation mode for your save related operations.

References:

Table-Valued Parameters: Basics

March 24, 2015 Leave a comment

You can use table-valued parameters (TVP) to send multiple rows of data to a Transact-SQL statement or a routine, such as a stored procedure or function, without creating a temporary table or many parameters.

Great news, you can use TVP with CodeFluent Entities! Let’s see how you can use TVP to bulk load rows based on a list of id.

Create a new CFQL method:

Note the usage of “[]” after the type name. The generated method is:

public static CustomerCollection LoadByIds(System.Guid[] ids)

And the generated stored procedure:

CREATE TYPE [dbo].[cf_type_Customer_LoadByIds_0] AS TABLE (
 [Item] [uniqueidentifier] NULL)
GO
CREATE PROCEDURE [dbo].[Customer_LoadByIds]
(
 @ids [dbo].[cf_type_Customer_LoadByIds_0] READONLY
)
AS
SET NOCOUNT ON
DECLARE @_c_ids int; SELECT @_c_ids= COUNT(*) FROM @ids
SELECT DISTINCT [Customer].[Customer_Id], [Customer].[Customer_FirstName], [Customer].[Customer_LastName], [Customer].[Customer_DateOfBirth]
    FROM [Customer]
    WHERE [Customer].[Customer_Id] IN (((SELECT * FROM @ids)))

RETURN
GO

Table-Valued Parameters require SQL Server 2008. Don’t forget to change the target of the SQL Server producer to use at least this version.

Additionally set Legacy String Array Mode to false :

Happy Coding,

The R&D Team.

References: http://www.softfluent.com/documentation/Methods_WorkingWithArrays.html

CodeFluent Entities vs Entity Framework : Cascade Delete

February 25, 2015 Leave a comment

Ensuring referential integrity is something very important in RDBMS. When you delete a customer you may want to delete all related information, this what is called Cascade Delete.

Let’s see how CodeFluent Entities and Entity Framework (with Model-First) handle this feature.

Entity Framework

First of all you have to add a navigation property:

Then you can select the association (the line between entities) and configure it:

The generated SQL contains:

-- --------------------------------------------------
-- Creating all FOREIGN KEY constraints
-- --------------------------------------------------

-- Creating foreign key on [CustomerId] in table 'OrderSet'
ALTER TABLE [dbo].[OrderSet]
ADD CONSTRAINT [FK_CustomerOrder]
    FOREIGN KEY ([CustomerId])
    REFERENCES [dbo].[CustomerSet]
        ([Id])
    ON DELETE CASCADE ON UPDATE NO ACTION;
GO

Entity Framework Model First does not allow cascade delete on many to many association:

CodeFluent Entities

As with EF, we also need to create a relation:

All parameters are available on the same screen. Instead of EF, it’s all English so everyone can understand options.

When using this option, the cascade delete is done by the generated stored procedure looks like:

BEGIN TRANSACTION
DELETE [Order] FROM [Order]
    INNER JOIN [Customer] ON ([Order].[Order_Customer_Id] = [Customer].[Customer_Id])
    WHERE ([Customer].[Customer_Id] = @Customer_Id)
DELETE FROM [Customer]
    WHERE ([Customer].[Customer_Id] = @Customer_Id)
COMMIT TRANSACTION

Maybe you prefer to use the SQL instruction “ON DELETE CASCADE”. This option is also available with CodeFluent Entities:

Using this setting the generated constraint now uses ON DELETE CASCADE:

ALTER TABLE [dbo].[Order] ADD CONSTRAINT [FK_Ord_Orr_Cus_Cus] FOREIGN KEY (
[Order_Customer_Id]
) REFERENCES [dbo].[Customer](
[Customer_Id]
) ON DELETE CASCADE

Conclusion

Both solutions support cascade delete functionality. CodeFluent Entities has two ways to support this feature and is understandable by non-technical people.

CodeFluent Entities vs Entity Framework: Computed property

February 16, 2015 Leave a comment

Computed properties are properties which are computed from other properties. For instance the full name is the concatenation of the first name and the last name. This value can be computed by the database or by the .NET code.

Let’s see how CodeFluent Entities and Entity Framework handle those properties.

Entity Framework

.NET

There is no magic, you have to add a partial class with a property FullName:

partial class Customer
{
    public string FullName
    {
        get { return string.Format("{0} {1}", this.FirstName, this.LastName); }
    }
}

This property is not part of the model so you cannot use it in T4 templates.

Database

Querying the database should be easy with EF, but in fact there are some subtleties. Here’s the Linq to Entities query:

var customers = from customer in context.Customer
                select new
                {
                    Id = customer.Id,
                    FullName = customer.FirstName + " " + customer.LastName
                };

If you look in details the result is not a list of Customer but a list of an anonymous type. In fact EF does not allows to instantiate a custom Entity object:

You can also define SQL function in the model, but you have to edit the Edmx file with an xml editor (without designer).

CodeFluent Entities

.NET

There are many possibilities:

1. As with Entity Framework we can add a new property in a partial class
2. We can also add a computed property directly to the model and code the OnGetFullName method in a partial class. This way we can benefit from the property when generating code from the model

private void OnGetFullName()
{
    this._fullName = string.Format("{0} {1}", this.FirstName, this.LastName);
}

3. When the computed property is a “string.Format” you can specify the format in the model so the code of the OnGetFullName method is automatically generated:

Database

The idea is to create a view which compute the full name.

Finally, you can load data from the SQL view using one line of code:

CustomerCollection.LoadCustomerWithFullName()

Conclusion

Both solutions allow to use computed properties. CodeFluent Entities provides some shorthand’s so you don’t always have to write code.

References:

CodeFluent Entities vs Entity Framework: Naming convention

February 12, 2015 Leave a comment

This is the first of many in a series of post covering the difference between Entity Framework 6 and CodeFluent Entities. Today we’re talking about naming convention.

Naming convention allows to transform the name of a concept in the model (entity, property, constraints, etc.) for generating database. For instance if you have an entity “Product” in your model, the generated table name may be “Product”, or “PRODUCT”, “prod” or maybe something else according to you naming convention. So naming convention is about standardization and also about making your DBA happy with the generating codeJ.

Entity Framework

Entity Framework Model-First doesn’t provide a simple way to apply a naming convention for the model. Instead you have to manually define names:

To automate the process you have to change default T4 templates located in Visual Studio installation folder, and the default generation workflow (TablePerTypeStrategy.xaml). Be sure to keep in sync the SQL template and the mapping (MSL) template.

Figure 1- Extract from the default T4 file

Then you can change model settings:

Entity Framework Code First has the notion of convention (does not work with Model First). This notion allows to set name of tables or properties:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     modelBuilder.Types().Configure(type => type.ToTable("EF_" + type.ClrType.Name));
     modelBuilder.Properties().Configure(prop => prop.HasColumnName("EF_" + prop.ClrPropertyInfo.Name));
}

Setting constraint names (foreign key names, index names) looks more complicated and requires more than one line of code.

CodeFluent Entities

CodeFluent Entities provides out of the box six naming conventions, and allows you to create your own naming convention.


 

To implement a custom naming convention you have to create a class that implements INamingConvention or inherits from BaseNamingConvention:

public class MyCustomConvention: BaseNamingConvention
{
 public override string GetName(INamedObject obj, IDictionary context)
 {
  Column column = obj as Column;
  if (column != null)
  {
   string name = (string)context["name"];
   Table table = (Table)context["table"];
   if (table != null)
   {
     column.DefaultName = "Default_" + table.Name + "_" + name;
   }
  }
  return base.GetName(obj, context);
 }

 public override string GetShortName(IShortNamedObject obj, IDictionary context)
 {
  Constraint constraint = obj as Constraint;
  if (constraint == null)
   return base.GetShortName(obj, context);

  return "myx_" + constraint.ConstraintType + "_" + constraint.Table.Name + "_" + constraint.ReferencedTable.Name;
 }
}

Conclusion

Entity Framework Model-First does not provide a simple way to define a naming convention. The Code-First approach is better for table name and column name, but it’s harder to name indices or foreign keys.

CodeFluent Entities provides out of the box six naming conventions, and let you write your own.

References :

 

Table-Valued Parameters: Basics

February 11, 2015 Leave a comment

First, what is Table-Valued Parameters ?

Table-valued parameters provide an easy way to marshal multiple rows of data from a client application to SQL Server without requiring multiple round trips or special server-side logic for processing the data.

You can use table-valued parameters (TVP) to send multiple rows of data to a Transact-SQL statement or a routine, such as a stored procedure or function, without creating a temporary table or many parameters.

Great news, you can use TVP with CodeFluent Entities! Let’s see how you can use TVP to bulk load rows based on a list of id.

Create a new CFQL method:

Note the usage of “[]” after the type name. The generated method is:

public static CustomerCollection LoadByIds(System.Guid[] ids)

And the generated stored procedure:

CREATE TYPE [dbo].[cf_type_Customer_LoadByIds_0] AS TABLE (
 [Item] [uniqueidentifier] NULL)
GO
CREATE PROCEDURE [dbo].[Customer_LoadByIds]
(
 @ids [dbo].[cf_type_Customer_LoadByIds_0] READONLY
)
AS
SET NOCOUNT ON
DECLARE @_c_ids int; SELECT @_c_ids= COUNT(*) FROM @ids
SELECT DISTINCT [Customer].[Customer_Id], [Customer].[Customer_FirstName], [Customer].[Customer_LastName], [Customer].[Customer_DateOfBirth]
    FROM [Customer]
    WHERE [Customer].[Customer_Id] IN (((SELECT * FROM @ids)))

RETURN
GO

Table-Valued Parameters require at least SQL Server 2008. Don’t forget to change the target of the SQL Server producer to use at least this version. Additionally set Legacy String Array Mode to false.

Additionally set Legacy String Array Mode to false.


References: http://www.softfluent.com/documentation/Methods_WorkingWithArrays.html

Happy coding,

The R&D Team.

WPF Universal Converter

February 3, 2015 Leave a comment

When you create an application using WPF, you often have to write converters to change one value to the desired type. The .NET Framework already provides some basics converter such as BooleanToVisibilityConverter. These converters are very specifics and not configurable. For example you cannot change the visibility from Collapsed to Hidden. We do not want to spend time to write common converter so we create the UniversalConverter.

The converter is located in the CodeFluent.Runtime.dll or CodeFluent.Runtime.Client.dll. Please use the Nuget Package Manager to add this Package on your project:

CodeFluentRuntime_Nuget

Let’s see how to use it!

Basic conversion

<Window.Resources>
    <windows:UniversalConverter x:Key="TypeConversionUniversalConverter" />
</Window.Resources>

<CheckBox IsChecked="{Binding Converter={StaticResource TypeConversionUniversalConverter},
   Mode=OneWay}" DataContext="true"/>
<CheckBox IsChecked="{Binding Converter={StaticResource TypeConversionUniversalConverter}, 
   Mode=OneWay}" DataContext="yes"/>

UniversalConverter uses ConvertUtilities to convert the value to the desired type so string values “true” and “yes” will be converted to the Boolean value “true”.

Switch Case syntax

You can create a list of cases to fit all your needs. For instance:

<windows:UniversalConverter x:Key="BooleanToVisibilityConverter">
    <cfr:UniversalConverter.Switch>
        <cfr:UniversalConverterCase Operator="Equal" Value="True" C
  onvertedValue="Visible" />
        <cfr:UniversalConverterCase Operator="Equal" Value="False" 
  ConvertedValue="Collapsed" />
    </cfr:UniversalConverter.Switch>
</cfr:UniversalConverter>

As a C# switch you can set a default value:

<cfr:UniversalConverter x:Key="BooleanToVisibilityConverter" DefaultValue="Visible">
    <cfr:UniversalConverter.Switch>
        <cfr:UniversalConverterCase Operator="Equal" Value="False" 
  ConvertedValue="Collapsed" />
    </cfr:UniversalConverter.Switch>
</cfr:UniversalConverter>

There are currently 13 operators:

  • Equal,
  • NotEqual,
  • GreaterThan,
  • GreaterThanOrEqual,
  • LesserThan,
  • LesserThanOrEqual,
  • Between: minimum and maximum value included => [min:max[,
  • StartsWith,
  • EndsWith,
  • Contains,
  • IsType: type match exactly,
  • IsOfType: type or direved types,
  • JavaScript: Yes, you can use JavaScript to evaluate a condition!

And some options:

  • StringComparison
  • Trim
  • Nullify

Here’s a list of examples using different operators:

Check if a string contains NewLine using JavaScript

<cfr:UniversalConverter x:Key="HasMultipleLinesConverter" DefaultValue="False">
    <cfr:UniversalConverter.Switch>
        <!--look for a CR or LF in the string string-->
        <cfr:UniversalConverterCase Value="/\r|\n/.exec(Value)!=null" 
  ConvertedValue="True" Operator="Javascript" />
    </cfr:UniversalConverter.Switch>
</cfr:UniversalConverter>

Set error message background and foreground color

<cfr:UniversalConverter x:Key="ErrorTextBackgroundConverter" DefaultValue="Red">
    <cfr:UniversalConverter.Switch>
        <cfr:UniversalConverterCase Value="" ConvertedValue="Transparent" />
    </cfr:UniversalConverter.Switch>
</cfr:UniversalConverter>
<cfr:UniversalConverter x:Key="ErrorTextForegroundConverter" DefaultValue="White">
    <cfr:UniversalConverter.Switch>
        <cfr:UniversalConverterCase Value="" ConvertedValue="Black" />
    </cfr:UniversalConverter.Switch>
</cfr:UniversalConverter>

Test if a value is over 21

<cfr:UniversalConverter x:Key="IsOver21Converter" DefaultValue="false">
    <cfr:UniversalConverter.Switch>
        <cfr:UniversalConverterCase Operator="GreaterThanOrEqual" Value="21" 
  ConvertedValue="true" Options="Convert" />
    </cfr:UniversalConverter.Switch>
</cfr:UniversalConverter>

Is teenager

<cfr:UniversalConverter x:Key="IsTeenagerConverter" DefaultValue="false">
    <cfr:UniversalConverter.Switch>
        <cfr:UniversalConverterCase Operator="Between" MinimumValue="13" 
  MaximumValue="20" ConvertedValue="true" Options="Convert" />
    </cfr:UniversalConverter.Switch>
</cfr:UniversalConverter>

Compare types

<cfr:UniversalConverter x:Key="TypeConverter" DefaultValue="false">
    <cfr:UniversalConverter.Switch>
        <cfr:UniversalConverterCase Operator="IsType" Value="System.String" 
  ConvertedValue="Type = String" />
        <cfr:UniversalConverterCase Operator="IsType" Value="System.Int32" 
  ConvertedValue="Type = int" />
        <cfr:UniversalConverterCase Operator="IsOfType" 
  Value="BaseClass, MyAssembly" ConvertedValue="Type is of type BaseClass" />
    </cfr:UniversalConverter.Switch>
</cfr:UniversalConverter>

Is empty

<cfr:UniversalConverter x:Key="IsEmptyConverter" DefaultValue="Not empty">
    <cfr:UniversalConverter.Switch>
        <cfr:UniversalConverterCase Operator="Equal" Options="Trim, Nullify" 
  ConvertedValue="Empty" />
    </cfr:UniversalConverter.Switch>
</cfr:UniversalConverter>

<TextBox x:Name="TextBox"/>
<TextBlock Text="{Binding ElementName=TextBox, Path=Text, 
  Converter={StaticResource IsEmptyConverter}}" />

If you need more examples, please let us know. Our team will be happy to help you J.

Happy converting,

The R&D team

Follow

Get every new post delivered to your Inbox.

Join 56 other followers