Archive

Archive for the ‘Developing Using CodeFluent Entities’ Category

CodeFluent Entities Tour 2016

January 21, 2016 Leave a comment

There are a few ways to get started with CodeFluent Entities. You can read the Getting Started section of our new product website or enjoy the new CodeFluent Entities Tour.

In this webinar a product team member explains how to start with CodeFluent Entities by creating your first application.

 

We share how CodeFluent Entities, a free Visual Studio plugin accelerates development while raising code quality and easing communication between business, developers and operations.

You really should check-out CodeFluent Entities Tour which is a recording of our latest webinar and shows it all in action.

CodeFluent Entities and Visual Studio 2015

July 24, 2015 Leave a comment

Good things come in pairs: Visual Studio 2015 is now available for download and CodeFluent Entities latest build (61214.820) runs great on it!

codefluent_vs_2015

You can learn more about Visual Studio 2015 here:

Visual Studio 2015 includes Entity Framework 7. This latest version and beyond only support code-base modeling, also know as “code first”. We are pleased to announce that we continue to support the “model first” approach by providing a graphical modeler to define your business model without needing to code. You should read our whitepaper to understand the benefits of “model first” software development.

You can download the latest version of CodeFluent Entities here, or update your version using the Licensing tool. Remember that you can follow the latest new features and bug fixes of CodeFluent Entities subscribing to this RSS.

Happy Modeling,

The R&D Team.

Team Work with CodeFluent Entities


Working on your own and working along a whole developers team are obviously not the same. As a team, you will experience issues that you would never encounter working alone.

In order to help you work in a harmless way with CodeFluent Entities in that context, we wrote a new paper about every little things you can configure while you are:

  • Designing your model collaboratively
  • Generating your own database
  • Handling work station custom connection strings
  • Using source control

You can get this paper here.

Happy Configurating,

The R&D Team.

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

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.

Custom Naming Convention

January 8, 2015 Leave a comment

Since CodeFluent Entities infers a meta-model from your model, before any producer is called to generate a single line of code, a full representation of your application is in-memory. Thanks to this inference step and the resulting meta-model, developers can apply application wide changes.

One of the possible application wide changes is to change the way all database objects are named through a naming convention. By default a set of naming conventions are provided by CodeFluent Entities:

  • FormatNamingConvention
  • LowerCaseNamingConvention
  • UpperCaseNamingConvention
  • DecamelizeNamingConvention
  • DecamelizeLowerCaseNamingConvention
  • DecamelizeUpperCaseNamingConvention

And you can also implement your own naming convention to fit your needs as we’ll see in this post.

Create the custom Naming Convention

The naming convention is a class so we create a class library project and add references to

  • CodeFluent.Runtime.dll
  • CodeFluent.Model.dll
  • CodeFluent.Model.Common.dll

Those DLL are located in the installation folder of CodeFluent Entities.

Create a class that implements IProjectNamingConvention or inherits from an existing Naming Convention:

using System.Collections;
using CodeFluent.Model.Common.Naming;
using CodeFluent.Model.Naming;
using CodeFluent.Model.Persistence;

namespace SoftFluent.Samples.CustomNamingConvention
{
    public class MyNamingConvention : FormatNamingConvention
    {
        public override string GetName(INamedObject obj, IDictionary context)
        {
            var procedure = obj as Procedure;
            if (procedure != null)
            {
                if (procedure.Table != null &&
                    procedure.Table.Entity != null &&
                    procedure.Table.Entity.Store != null)
                {
                    return procedure.Table.Entity.Store.Name + "_" + base.GetName(obj, context);
                }

                if (procedure.Method != null &&
                    procedure.Method.Entity != null &&
                    procedure.Method.Entity.Store != null)
                {
                    return procedure.Method.Entity.Store.Name + "_" + base.GetName(obj, context);
                }
            }

            return base.GetName(obj, context);
        }
    }
}

This naming convention prefix parameter name with the store name

Setting the naming convention

Add a reference in the CodeFluent entities project to your class library project:

Now you can open model project properties and set the naming convention with its full type name:

 

That’s all J Now all procedures are prefixed by the store name:

Happy naming,

The R&D Team

Multi-tenant using multiple Schemas

December 4, 2014 Leave a comment

In this post we will see how to create a multi-tenant application using one schema by tenant. The idea is to create one CodeFluent Entities model and use it to generate as many database schemas as needed.

The generated database will contains one schema by tenant:

But to keep the usage as simple as possible, only one Business Object Model is generated. The schema is selected at runtime:

Note: The following procedure uses the Custom meta-compiler host feature which is available only with CodeFluent Entities Personal or Ultimate

Generate the database

 

The idea is to keep the model untouched, so we create a console application which:

  • Load the CodeFluent Entities model
  • Change entity schema in memory (the original model won’t be changed)
  • Generate code
class Program
{
    private static string _schema;
    private static string _projectPath;
    private static bool _changeTargetDirectory;

    static void Main()
    {
        _projectPath = CommandLineUtilities.GetArgument("path", (string)null) ?? CommandLineUtilities.GetArgument(0, (string)null);
        _schema = ConvertUtilities.Nullify(CommandLineUtilities.GetArgument("schema", (string)null) ?? CommandLineUtilities.GetArgument(1, (string)null), true);
        _changeTargetDirectory = CommandLineUtilities.GetArgument("changeTargetDirectory", true);

        // Load the model
        Project project = new Project();
        project.Entities.ListChanged += Entities_ListChanged; // Change schema as soon as the entity is loaded
        project.Load(_projectPath, ProjectLoadOptions.Default);

        // Update producer target directory
        if (!string.IsNullOrEmpty(_schema) && _changeTargetDirectory)
        {
            foreach (var producer in project.Producers)
            {
                var sqlServerProducer = producer.Instance as SqlServerProducer;
                if (sqlServerProducer != null)
                {
                    sqlServerProducer.Production += SqlServerProducer_Production;
                }
            }
        }

        // Generate code
        project.Produce();
    }

    private static readonly HashSet<IProducer> _producers = new HashSet<IProducer>();
    private static void SqlServerProducer_Production(object sender, ProductionEventArgs e)
    {
        SqlServerProducer sqlServerProducer = sender as SqlServerProducer;
        if (sqlServerProducer == null)
            return;

        if (_producers.Contains(sqlServerProducer))
            return;

        sqlServerProducer.EditorTargetDirectory = Path.Combine(sqlServerProducer.EditorTargetDirectory, _schema);
        _producers.Add(sqlServerProducer);
    }

    private static void Entities_ListChanged(object sender, ListChangedEventArgs e)
    {
        if (e.ListChangedType != ListChangedType.ItemAdded)
            return;

        var entityCollection = sender as EntityCollection;
        if (entityCollection == null || e.NewIndex < 0 || e.NewIndex >= entityCollection.Count)
            return;

        Entity entity = entityCollection[e.NewIndex];
        Console.WriteLine("Changing schema of entity '{0}' from '{1}' to '{2}'", entity.ClrFullTypeName, entity.Schema, _schema);
        entity.Schema = _schema;
    }
}

That’s it… We can now use this console application to generate the persistence layer:

SoftFluent.MultiTenantGenerator.exe "Sample.Model\Sample.Model.cfxproj" "SoftFluent"
SoftFluent.MultiTenantGenerator.exe "Sample.Model\Sample.Model.cfxproj" "Contoso"

You can create a script to call program this for each tenant.

Select the right tenant at runtime

 

We generate only one Business Object Model (BOM) for all tenants. This BOM access by default to the schema specified in the CodeFluent Entities model. In our case we want to change this schema at runtime depending on the context (user, Uri, etc.).

To access the database, the generated code use CodeFluentPersistence:

CodeFluentPersistence has a hook system (ICodeFluentPersistenceHook) that allows to change the default CodeFluentPersistence behavior. In our case the idea is to change the CreateStoredProcedureCommand method behavior to use the right schema. Here’s the code:

public class SchemaPersistenceHook : BasePersistenceHook
{
    private bool _processing = false;
    public override bool BeforeCreateStoredProcedureCommand(string schema, string package, string intraPackageName, string name)
    {
        if (_processing)
            return false;

        _processing = true;
        try
        {
            string currentSchema = GetTenant();
            Persistence.CreateStoredProcedureCommand(currentSchema, package, intraPackageName, name);
        }
        finally
        {
            _processing = false;
        }

        return true;
    }

    public virtual string GetTenant()
    {
            // TODO: Implement your own logic
            return CodeFluentUser.Current.UserDomainName;
    }
}

Finally we have to declare our persistence hook in the configuration file so CodeFluentPersistence will use it automatically:

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

  <Sample persistenceHookTypeName="Sample.SchemaPersistenceHook, Sample" />
</configuration>

That’s it. With a few lines of codes and the power of CodeFluent Entities you can change the default behavior to fit your needs. Can you do the same with other products?

The source code is available on our GitHub repository.

Happy tenanting,

The R&D team