Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DataService Query Company #14

Closed
richard-brash opened this issue Jan 22, 2014 · 6 comments
Closed

DataService Query Company #14

richard-brash opened this issue Jan 22, 2014 · 6 comments

Comments

@richard-brash
Copy link

The class Infusionsoft.Tables.Company does not include a property: Company. (for the company name). Instead, the property CompanyName is mapped to the field Company.

However, when using the DataService.Query method and adding a query parameter for CompanyName, an error is thrown [NoFieldFound] No field found: Company.CompanyName.

        var results = client.DataService.Query<ISTables.Company>(
            new DataPage(req.Take, req.Skip),
            q => q.Add(c=>c.CompanyName, req.Filter + "%"),
            p => p.Include(c => c.Id)
                .Include(c => c.CompanyName)
                .Include(c => c.City)
                .Include(c => c.Phone1)
            ).ToList(); 
@trbngr
Copy link
Contributor

trbngr commented Jan 22, 2014

Unfortunately, this infusionsoft API is one hell of a moving target.

Likely the best option is to apply a change property name refactoring to the property.

I accept pull requests. ;)

If you can't get to it, let me know and I'll do it tomorrow afternoon.

Cheers,
Chris

@richard-brash
Copy link
Author

Chris,

Thanks for the quick response. I had abandoned using another library because it had been error prone and I ended up writing my own wrapper as needed but it was never complete. I found yours on NuGet and decided to give it a try for this project. As it is, I don't have much time to find and fix this issue. For now, I am using the standard method signature instead of the LINQ expressions just so I can move forward. If I get time, I'll take a look and see if I can push a fix unless you beat me to it.

Thanks again,
Richard

On Jan 22, 2014, at 1:46 AM, Chris Martin notifications@github.com wrote:

Unfortunately, this infusionsoft API is one hell of a moving target.

Likely the best option is to apply a change property name refactoring to the property.

I accept pull requests. ;)

If you can't get to it, let me know and I'll do it tomorrow afternoon.

Cheers,
Chris


Reply to this email directly or view it on GitHub.

@piranout
Copy link

There is a problem with the way Infusionsoft designed the Company table. Instead of Name or CompanyName, they called the name field Company. C# doesn't allow property names to be the same as their enclosing type though. So the generated class creates an alias—CompanyName—and tells XmlRpc to map it to the Company field. The definition looks like this:

  [XmlRpcMember("Company")]
  [Access(Access.Edit | Access.Delete | Access.Add | Access.Read)]
  public string CompanyName { get; set; }

Ultimately, the query translator needs to check if the XmlRpcMember attribute name matches the property name. If they don't match, it needs to use the attribute value when serializing the query.

Unfortunately, even using the untyped Query method, I get zero results for a query that should have 200+. The only way I can query companies right now is to fetch them all & do my LINQ filtering on the client side. Here's a wildcard query (name starts with A) that I think should work, but either I'm missing something or something outside my control is borked:

 var queryData = new XmlRpcStruct() { { "Company", "A%" } };
 var cs = client.DataService.Query(
    table: "Company",
    limit: 1000,
    page: 1,
    queryData: queryData,
    selectedFields: new[] {"CompanyID", "Company", "State", "PostalCode", "Country"});

@piranout
Copy link

I have a fix for this. The query builder just needs a dictionary of property names that don't match Infusionsoft's actual column names. Here's the patch that got it working for me (I can do a normal query on CompanyName now; this should also enable LINQ query expressions to address any field that's not named the same as the table column). First, add the following extension class in the InfusionSoft namespace:

internal static class QueryBuilderExtensions
{
    private static Dictionary<Type, Dictionary<string, string>> _columnNames;
    private static Dictionary<Type, Dictionary<string, string>> ColumnNames
    {
        get
        {
            return _columnNames ?? (_columnNames = new Dictionary<Type, Dictionary<string, string>>());
        }
    }
    public static string GetColumnName<T>(this IQueryBuilder<T> builder, string propertyName) where T : ITable
    {
        if (!ColumnNames.ContainsKey(typeof(T)))
        {
            ColumnNames[typeof(T)] = new Dictionary<string, string>();
            typeof(T).GetProperties()
                .Where(p => !p.Name.Equals("CustomFields") && !p.Name.EndsWith("Comparer"))
                .ToList()
                .ForEach(p =>
                {
                    var attributes = p.GetCustomAttributes(typeof(XmlRpcMemberAttribute), false);
                    if (!attributes.Any())
                        return;
                    var attribute = attributes.Cast<XmlRpcMemberAttribute>().First();
                    if (!String.IsNullOrEmpty(attribute.Member) && attribute.Member != p.Name)
                    {
                        ColumnNames[typeof(T)].Add(p.Name, attribute.Member);
                    }
                });
        }
        return ColumnNames[typeof(T)].ContainsKey(propertyName) ? _columnNames[typeof(T)][propertyName] : propertyName;
    }
}

Then change the main overload of QueryBuilder.Add as such:

public IQueryBuilder<T> Add<TV>(Expression<Func<T, TV>> expression, TV value, ValuePosition valuePosition)
{
    string name = Express.PropertyWithLambda(expression).Name;
        name = this.GetColumnName(name);
    _dictionary.Add(name, BuildPositionalValue(valuePosition, value));
    return this;
}

@trbngr
Copy link
Contributor

trbngr commented Mar 30, 2014

Excellent. Thanks for the effort.

If you issue a pull request, I'll merge it in.

@trbngr trbngr closed this as completed Mar 30, 2014
@piranout
Copy link

Done, thanks! Let me know if everything's satisfactory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants