Page 1 of 1

Factor out common LINQ elements (linqconect)

Posted: Fri 04 May 2012 14:19
by drysg
If you look at the code below, you see a great deal of repetition in reading and extracting the values from a LinqQuery Table. It is easy enough to create a function that would accept a dotconnect context model (in this case the context is GPL, and the context Model is GPL.GPLModel), but what about the c.Type, c.Creator, c.Distributor, c.Handling). I have looked all through the methods of GPL.GPLModel (created by LinqConnect, but I am still not getting it.

As you can see, I was able to factor out some code into the private makeResponse method.

Code: Select all

 private ItemList makeResponse(IEnumerable<Item> data)
        {
            Item[] results = data.ToArray<Item>();
            ItemList response = new ItemList
            {
                count = results.Length,
                results = results
            };
            return response;
        }

        public ItemList Mcreators()
        {
            GPL.GPLModel context = new GPL.GPLModel();
            var rows =
                from c in context.MCreators
                select new Item
                {
                    idx = c.Idx,
                    name = c.Creator
                };
            return makeResponse(rows);
        }

        public ItemList Mtypes()
        {
            GPL.GPLModel context = new GPL.GPLModel();
            var rows =
                from c in context.MTypes
                select new Item
                {
                    idx = c.Idx,
                    name = c.Type
                };
            return makeResponse(rows);
        }


        public ItemList Mhandlings()
        {
            GPL.GPLModel context = new GPL.GPLModel();
            var rows =
                from c in context.MHandlings
                select new Item
                {
                    idx = c.Idx,
                    name = c.Handling
                };
            return makeResponse(rows);
        }

        public ItemList Mdistributors()
        {
            GPL.GPLModel context = new GPL.GPLModel();
            var rows =
                from c in context.MDistributors
                select new Item
                {
                    idx = c.Idx,
                    name = c.Distributor
                };
            return makeResponse(rows);
        }

        public ItemList McolumnNames()
        {
            PropertyInfo[] propertyInfos;
            propertyInfos = typeof(CatalogEntry).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            int id = 0;
            var rows =
                from p in propertyInfos
                select new Item
                {
                    idx = id++,
                    name = p.Name
                };
            return makeResponse(rows);
        }

Re: Factor out common LINQ elements (linqconect)

Posted: Tue 08 May 2012 13:32
by MariiaI
Could you please specify the definitions of the classes used in the sample and describe the scenario you are trying to implement?
As far as I can understand, the Item class has two properties ('ID' and 'Name') which you are trying to extract from entities of other types. Am I correct? If yes, you can try performing the following steps to do so:
- make the private fields corresponding to ID and Name protected;
- inherit other classes ("MDistributor" etc.) from the "Item" class;
- change inherited classes so that they use the fields of Item; for example, if the field used for 'Name' is called 'name', the MCreator.Creator property may be implemented as follows:

Code: Select all

class MCreator : Item  {
public string Creator {
  get { return name; }
  set { name = value; }
}}
- change the storage members of the inherited classes' properties:

Code: Select all

[Column(Name = @"""Creator""", Storage = "name", DbType = "VARCHAR(40)")]
Please tell us if this helps.

Re: Factor out common LINQ elements (linqconect)

Posted: Tue 08 May 2012 13:47
by drysg
I did not want to burden you with all the code and class definitions. So I apologize for being too brief. (I have enclosed the project to you in email previously, and I am resending via that channel).

Item and ItemList are public classes for holding data that is to be serialized via JSON by WCF .NET services. (i.e. DataContracts)

Code: Select all

[DataContract]
    public class ItemList
    {
        int _count;
        Item[] _results;

        [DataMember]
        public int count
        {
            get { return _count; }
            set { _count = value; }
        }

        [DataMember]
        public Item[] results
        {
            get { return _results; }
            set { _results = value; }
        }
    }

    [DataContract]
    public class Item
    {
        int _idx;
        String _name;

        [DataMember]
        public int idx
        {
            get { return _idx; }
            set { _idx = value; }
        }

        [DataMember]
        public String name
        {
            get { return _name; }
            set { _name = value; }
        }
    }
}
Mccreators, Mtypes, Mhandling etc. cannot inherit from Item or ItemList. These are classes created by your LinqConnect. In the snippet below: GPL is the namespace I gave the dataContext and GPLModel is the DataContext. context.MTypes is a class mapped to a DotConnnect LinqConnect Table that was created with LinqConnect. It does not inherit from Item.

Code: Select all

        public ItemList Mtypes()
        {
            GPL.GPLModel context = new GPL.GPLModel();
            var rows =
                from c in context.MTypes
                select new Item
                {
                    idx = c.Idx,
                    name = c.Type
                };
            return makeResponse(rows);
        }

Re: Factor out common LINQ elements (linqconect)

Posted: Thu 10 May 2012 09:36
by MariiaI
To solve your task with the extracting Item class properties ('ID' and 'Name') from entities of other types, you could try to change the LinqConnect Template specifically for this goal.

For more information about templates see in Entity Developer documentation:
User Interface Reference->Template Editor-> Basic Operations With Templates

Re: Factor out common LINQ elements (linqconect)

Posted: Thu 10 May 2012 13:55
by drysg
Cute,

So it seems that the best way would be to extend each Template to provide a generic property called name that would fetch either c.Type, c.Owner, etc. - i.e. I would extend the each class to provide a generic property.

The only issue here is that the work involved in extending the Template is more than leaving the code unfactored. (see below) so I suggest for your future work, to create a helper method to your <TABLE> class that uses introspection and reflection to allow me to add methods on the fly:

e.g. Table.addMethod("methodName", delegate, parameter array) and then execute this as a closure in the context of the Table (so that I can get to the properties of the TABLE instance and also refer to "this" properly).

What is shown below is what I see as too much work (and too prone to errors)

Code: Select all

Copy Code 
<#
// Empty template for Devart Entity Developer C# code generation.
// Copyright (c) 2008-2012 Devart. All rights reserved.
#>
<#@ template language="C#" #>
<#@ extended name="Load" owner="RelationProperty" type="System.Boolean" default="true" #>
<#
// Settings
  output.Extension = ".cs";
  output.FileName = model.FileName + "DataLoadOptionsFactory";
#>
using Devart.Data.Linq;
using Domain;

namespace <#=!string.IsNullOrEmpty(model.ContextNamespace) ? codeProvider.GetValidIdentifier(model.ContextNamespace) : codeProvider.GetValidIdentifier(model.Name)#> {

  public static class DataLoadOptionsFactory {
    
    public static DataLoadOptions CreateLoadOptions() {

       DataLoadOptions loadOptions = new DataLoadOptions();
<#
  foreach (Class cls in model.Classes)
    foreach (RelationProperty relationProperty in cls.RelationProperties)
      if ((bool)relationProperty.GetProperty("Load")) {
#>
       loadOptions.LoadWith<<#= cls.Name #>>(c => c.<#= relationProperty.Name #>);
<#
      }
#>
       return loadOptions;
    } 
  }
}
 

Re: Factor out common LINQ elements (linqconect)

Posted: Thu 10 May 2012 16:09
by drysg
I.e. I am looking at creating an extension to your Table<TEntity> type you created for me in LinqConnect: which is called GPL.MType:

Code: Select all

namespace GPLExtension
{
    public static class GPLAddOnMethods
    {
        public static string getName(this GPL.MType me)
        {
            return me.Type;
        }
    }
}
This provides a generic way of getting the name, but I am still looking for a way of passing in the GPL.GPLModel in a generic way?

Code: Select all

private getvalues(Table<TEntity> table) {

for rows = from c in table
                select new Item
                {
                    idx = c.Idx,
                    name = c.getName();
                };

Re: Factor out common LINQ elements (linqconect)

Posted: Fri 11 May 2012 10:16
by MariiaI
To work with these entities uniformly, you can extract a common interface from them (say, 'IItem') with properties "ItemId" and "ItemName".
Specify that the entities implement this interface in the model (click on model canvas and in LinqConnectContextModel Properties set the Entity Base property to the interface IItem).
The interface implementation needs to be done for each class separately, but it does not require changing the generated code, because entity classes are partial.

With the interface IItem method GetItems can be done as generic.
We've sent you a sample project. Please check that it is not blocked by your mail filter.

Re: Factor out common LINQ elements (linqconect)

Posted: Mon 14 May 2012 15:27
by drysg
This works fine. I was getting too C# V4 ish. I trying out dynamic types, Class Extensions, and the like. Which was interfering with the simple Interface based way of dealing with this polymorphism.

(My issue is that I am doing more and more javascript and losing my ability to think in terms of strongly typed languages).

Re: Factor out common LINQ elements (linqconect)

Posted: Tue 15 May 2012 08:24
by MariiaI
Glad to see that the problem was resolved.