3

In my edmx model are 2 related tables: Challenge and ChallengeNote (has FK back to ChallengeID)

I can do this in breeze all day long

var qry = dataservice.getQuery("Challenges");

However, this fails every time:

var qry = dataservice.getQuery("Challenges").expand("ChallengeNotes");

The searchFailed is called and is the only error information in the console.

return dataservice.execute(qry.inlineCount(true))
        .then(seachSucceeded)
        .fail(searchFailed);
  • Does Breeze support relational data like this?
  • Does one need to write some custom code to support?
  • What am I missing?

Here's related answered question, but I was already following (unless I missed something) the answer's solution (and why I have the 2 context.Configuration settings in my ContextProvider). breezejs-error-when-loading-an-entity-with-related-data

Here's another similar question that's been unanswered breeze-expand-query-fails-with-object-object-has-no-method-getproperty

Here's my provider code (want to use the BeforeSaveEntity override further on in the project):

public class ModelProvider : EFContextProvider<ModelEntities>
{
    public ModelProvider()
        : base() 
    {
        this.Context.Configuration.LazyLoadingEnabled = false;
        this.Context.Configuration.ProxyCreationEnabled = false;            
    }
}

Here's my controller code:

[BreezeController]
public class DataController : ApiController
{
    readonly ModelProvider _contextProvider = new ModelProvider();

    [HttpGet]
    public string Metadata()
    {
        return _contextProvider.Metadata();
    }

    [Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
    [HttpGet]
    public IQueryable<Challenge> Challenges()
    {
        return _contextProvider.Context.Challenges.Include(x => x.ChallengeNotes);
    }

    [HttpPost]
    public SaveResult SaveChanges(JObject saveBundle)
    {
        return _contextProvider.SaveChanges(saveBundle);
    }

    [HttpGet]
    public IQueryable<ChallengeNote> ChallengeNotes()
    {       
        return _contextProvider.Context.ChallengeNotes;
    }
}

When I browse to the URL, it's including the related entity: http://localhost:53644/breeze/data/Challenges?$filter=Active%20eq%20true&$top=10&$expand=ChallengeNotes&$inlinecount=allpages

Here is the data coming from the Controller json results

At this point all things, imo, are pointing to Breeze configuration on either the Server or Client.

TIA


Breeze absolutely does support this, but you do need to make sure that your Entity Framework model is set up correctly. Take a look at the DocCode sample in the Breeze zip for a number of examples of using both expand (client side) or EF include (server side) clauses.

One guess about your problem is that you are using the Breeze camelCasing naming convention and therefore your "expand" clause should be

var qry = dataservice.getQuery("Challenges").expand("challengeNotes");

i.e. "challengeNotes" (note the casing) is the name of the client side property that corresponds to a server side property of "ChallengeNotes". To clarify, "expand" clauses take the names of client side "properties" as parameters and property names are what are transformed as a result of the Breeze.NamingConvention.

In contrast, a query resource name i.e. "Challenges" in your example is the name of the server side resource ( as a result of marking your "Challenges" method with the [HttpGet] annotation. This name is NOT affected by the NamingConvention.

Side notes: Your example has both an expand and an Include clause. Either of these is sufficient all by itself. You do not need both. In general you can either include an "expand" clause in your client side query OR have an Entity Framework "Include" clause on the server. The advantage of the first is that you can control the expand on the client, the advantage of the second is that you can insure that every query for a specified resource always fetches some related entities.

Hope this helps!

4

1 回答 1

2

Breeze 绝对支持这一点,但您确实需要确保您的实体框架模型设置正确。查看 Breeze zip 中的 DocCode 示例,了解一些使用 expand(客户端)或 EF include(服务器端)子句的示例。

关于您的问题的一个猜测是您使用的是 Breeze camelCasing 命名约定,因此您的“扩展”子句应该是

var qry = dataservice.getQuery("Challenges").expand("challengeNotes");

即“challengeNotes”(注意大小写)是客户端属性的名称,对应于“ChallengeNotes”的服务器端属性。澄清一下,“扩展”子句将客户端“属性”的名称作为参数,而属性名称是 Breeze.NamingConvention 的结果。

相反,查询资源名称,即您的示例中的“挑战”是服务器端资源的名称(作为使用 [HttpGet] 注释标记您的“挑战”方法的结果。此名称不受命名约定的影响。

旁注:您的示例同时具有扩展和包含子句。这些中的任何一个本身就足够了。你不需要两者。通常,您可以在客户端查询中包含“扩展”子句,也可以在服务器上包含实体框架“包含”子句。第一个的好处是您可以在客户端控制扩展,第二个的好处是您可以确保对指定资源的每个查询总是获取一些相关的实体。

希望这可以帮助!

于 2013-11-09T01:58:09.140 回答