Giter VIP home page Giter VIP logo

breeze.server.net's Introduction

Breeze Data Management for .NET Servers

Breeze is a library from IdeaBlade that helps you manage data in rich client applications. If you store data in a database, query and save those data as complex object graphs, and share these graphs across multiple screens of your JavaScript or C# client, Breeze is for you.

Client-side querying, caching, dynamic object graphs, change tracking and notification, model validation, batch save, offline โ€ฆ all part of rich data management with Breeze. Breeze clients communicate with any remote service that speaks HTTP and JSON.

Breeze lets you develop applications using the same powerful idioms on the client and server. You can

  • query with a rich query syntax
  • navigate the graph of related entities
  • track changes as you add/change/delete entities
  • perform client-side validation
  • save all changes in a single transaction
  • use the same entity model on the server and client

Install from NuGet

.NET Core

For .NET Core (2 through 8) and Entity Framework Core (2 through 8), find the following packages in NuGet.

Note: Version 7.1 or later of each package is for .NET 5, 6, 7, and 8, whereas Version 3.x is for .NET Core 3 and Version 1.x is for .NET Core 2.

For a typical EFCore application, you would install the first two packages. For an NHibernate application, install the first package and Breeze.Persistence.NH. The last two packages are dependencies that are automatically installed by the other packages.

.NET Framework

See the docs for .NET 4.x NuGet packages

Documentation

See the docs for more info about what Breeze does and how to use it.

Set the release notes for changes in the latest version.

Examples

See some examples of how to use Breeze .NET server with clients written in Angular, Aurelia, React, and Vue in the Northwind-Demo.

See the TempHire application for a richer example showing proper architectural patterns.

Sources

The sources for this package are in the breeze.server.net repo. Please file issues and pull requests against that repo.

Source directories:

  • AspNet - Support for .NET Framework up to 4.8
  • AspNetCore-v3 - Support for .NET Core 3.1
  • AspNetCore - Support for .NET Core 2
  • DotNet - Support for .NET 5+
  • Old - Old code related to initial Core support
  • Tests - Test projects for running the client-driven test suite. Latest test projects are in Tests/Test.AspNetCore.EFCore.
  • build - Build scripts for .NET Framework and .NET Core up to 3.1. Build tools for .NET 5 and above are in DotNet/tools.

Upgrading from .NET Framework to Core

The underlying concepts are the same, but there are a few major changes

  • The ContextProvider class is now PersistenceManager.
  • The [BreezeController] and [EnableBreezeQuery] attributes have been replaced by [BreezeQueryFilter] attribute.
  • Breeze JSON query format is preferred over OData. You will need to use Breeze 2.x on the client, and use the UriBuilderJsonAdapter (not the UriBuilderOdataAdapter).

See the Northwind-Demo for steps to set up a new .NET Core server.

See the UPGRADE document for information on upgrading Breeze Client from 1.x to 2.x.

Building Breeze

The recent sources and solutions are in the breeze.server.net repo under the DotNet folder. Building is just a matter of:

  1. Installing the required version of .NET SDK
  2. Opening the appropriate solution in Visual Studio
  3. Restoring NuGet packages
  4. Rebuilding the solution

Test solutions are in the Tests/Test.AspNetCore.EFCore folder.


If you have discovered a bug or missing feature, please create an issue in the breeze.server.net github repo.

If you have questions about using Breeze, please ask on Stack Overflow.

If you need help developing your application, please contact us at IdeaBlade.

breeze.server.net's People

Contributors

bbdhiveteam avatar biegehydra avatar ccrowhurstram avatar clickonben avatar colinblair avatar dependabot[bot] avatar jtraband avatar lnu avatar marcelgood avatar mcpappas avatar nateradebaugh avatar steveschmitt avatar tschettler avatar wardbell avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

breeze.server.net's Issues

AspnetCore: EntitySet not found for type...Sequence contains no matching element

I am attempting to implement something similar, but simpler, to NorthWind DTO example under the breeze.js.samples repo.

I can add and update my EF entities by way of my DTO objects without error. If I delete one however, I get the error.

System.ArgumentException: EntitySet not found for type MyApp.Web.Models.Tile ---> System.InvalidOperationException: Sequence contains no matching element
   at System.Linq.Enumerable.First[TSource](IEnumerable`1 source, Func`2 predicate)
   at Breeze.Persistence.EF6.EFPersistenceManager`1.GetEntitySetName(Type entityType)
   at Breeze.Persistence.EF6.EFPersistenceManager`1.GetKeyValues(Object entity)
   --- End of inner exception stack trace ---
   at Breeze.Persistence.EF6.EFPersistenceManager`1.GetKeyValues(Object entity)
   at Breeze.Persistence.EF6.EFPersistenceManager`1.GetKeyValues(EntityInfo entityInfo)
   at Breeze.Persistence.SaveWorkState.<ToSaveResult>b__20_5(EntityInfo entityInfo)
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at System.Linq.Enumerable.<SelectManyIterator>d__16`2.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Breeze.Persistence.SaveWorkState.ToSaveResult()
   at Breeze.Persistence.PersistenceManager.SaveChanges(JObject saveBundle, TransactionSettings transactionSettings)
   at MyApp.Web.Controllers.ProfileController.SaveChanges(JObject req)
   at lambda_method(Closure , Object , Object[] )
   at Microsoft.AspNetCore.Mvc.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__27.MoveNext()

I am hooking into BeforeSaveEntities and AfterSaveEntities and using Automapper. I can see the Sql generated executes fine. It has something to do with turning the response into valid response for SaveChanges.

Not sure why an insert and update would function, but a delete wouldn't.

public SaveResult SaveChanges([FromBody]JObject req)
{
	if (UserID != null)
	{
		_manager.BeforeSaveEntitiesDelegate += BeforeSaveEntities;
		_manager.AfterSaveEntitiesDelegate += AfterSaveEntities;

		var results = _manager.SaveChanges(req);
		return results;
	}

	return null;
}
		
private static readonly List<(Type ClientType, Type ServerType)> _dtoMap = new List<(Type, Type)>
{
	( typeof(Web.Models.Tile), typeof(Data.Models.Tile) )
};


private Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap)
{         
	foreach (var item in _dtoMap)
	{
		if (saveMap.TryGetValue(item.ClientType, out List<EntityInfo> clientGroup))
		{
			// We don't persist client entities
			saveMap.Remove(item.ClientType);

			if (saveMap.TryGetValue(item.ServerType, out List<EntityInfo> serverGroup) == false)
				saveMap[item.ServerType] = serverGroup = new List<EntityInfo>();

			foreach (var clientEntityInfo in clientGroup)
			{
				var serverEntity = _mapper.Map(clientEntityInfo.Entity, item.ClientType, item.ServerType);
				var serverEntityInfo = _manager.CreateEntityInfo(serverEntity, clientEntityInfo.EntityState);
				
				if (clientEntityInfo.AutoGeneratedKey != null)
				{
					// Potential optmization: Cache this somewhere, or define it, or even create some sort of interface
					// on the client dto. I was thinking cache so we don't dirty up the dto...more.
					var map = _mapper.ConfigurationProvider.FindTypeMapFor(item.ClientType, item.ServerType);
					var prop = map.GetPropertyMaps().First(pm => pm.SourceMember == item.ClientType.GetProperty(clientEntityInfo.AutoGeneratedKey.PropertyName));

					clientEntityInfo.AutoGeneratedKey.PropertyName = prop.DestinationProperty.Name;
					clientEntityInfo.AutoGeneratedKey.Entity = serverEntity;
				}

				serverEntityInfo.UnmappedValuesMap = clientEntityInfo.UnmappedValuesMap;
				serverEntityInfo.OriginalValuesMap = clientEntityInfo.OriginalValuesMap;
				serverEntityInfo.AutoGeneratedKey = clientEntityInfo.AutoGeneratedKey;
				serverEntityInfo.ForceUpdate = clientEntityInfo.ForceUpdate;

				serverGroup.Add(serverEntityInfo);
			}
		}
	}

	return saveMap;
}

private void AfterSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap, List<KeyMapping> keyMappings)
{
	foreach (var item in _dtoMap)
	{
		if (saveMap.TryGetValue(item.ServerType, out List<EntityInfo> serverGroup))
		{
			// We don't persist client entities
			saveMap.Remove(item.ServerType);

			if (saveMap.TryGetValue(item.ClientType, out List<EntityInfo> clientGroup) == false)
				saveMap[item.ClientType] = clientGroup = new List<EntityInfo>();

			foreach (var serverEntityInfo in serverGroup)
			{
				var clientEntity = _mapper.Map(serverEntityInfo.Entity, item.ServerType, item.ClientType);
				var clientEntityInfo = _manager.CreateEntityInfo(clientEntity, serverEntityInfo.EntityState);

				clientEntityInfo.UnmappedValuesMap = serverEntityInfo.UnmappedValuesMap;
				clientEntityInfo.OriginalValuesMap = serverEntityInfo.OriginalValuesMap;
				clientEntityInfo.AutoGeneratedKey = serverEntityInfo.AutoGeneratedKey;
				clientEntityInfo.ForceUpdate = serverEntityInfo.ForceUpdate;

				clientGroup.Add(clientEntityInfo);
			}

			// Update the key mappings. Used when new items are created.
			var serverName = item.ServerType.FullName;
			var clientName = item.ClientType.FullName;

			keyMappings.ForEach(keyMapping =>
			{
				if (keyMapping.EntityTypeName == serverName)
					keyMapping.EntityTypeName = clientName;
			});
		}
	}
}

This happens anytime there is a delete. It could be by itself or it could come along with other changes. Either way, I always get that error.

I am using the EF as a designer for my metadata. Maybe something isn't right there? Still, not sure why that would only affect deletes.

SQL Query Tunning

Hello,
I am not sure if this issue relates to Breeze Context Provider or EF SqlProvider but here it goes.
We have an ASP.NET Web API with EF 6.1.3 model and today I noticed an interesting issue where if we request from the API method to sort by, expand and take/skip 20 rows and expand on multiple tables/entities, this translates to the following SQL query: JOIN on all rows in the primary table/entity against all expands, then sort then skip. Shouldn't it expand after filtering, skipping and sorting?

Entities deleted on server returned to server without info that they have been deleted.

This issue is related to this issue on SO:
http://stackoverflow.com/questions/16651889/entity-deleted-on-the-server-will-remain-unchanged-on-the-client-default-breeze

In my applicaiton, I add entities (marked "Deleted") to the saveMap in BeforeSaveEntities on the server. They get deleted on the server, but are returned to the client with no indication that they have been deleted. The client therefore has no chance of knowing that a server-deleted entity should be removed from the client cache.

Is there any way to inform the client that an entity has been deleted on the server (in BeforeSaveEntities)?

Metadata-only EFContextProvider

I followed the instructions from:
http://breeze.github.io/doc-js/metadata-with-ef.html

One thing I noticed is that the called to Metadata() hangs for 15 seconds (connection timeout) and then returns the data. I put in a fake connection string with a command timeout of 1 and it only hangs for about 1.6 seconds. Since I wrapped all this in a static, I only incur this penalty the first time.

I guess it probably isn't really a Breeze bug. I'm guessing it is more about the DbContext. Maybe there is something that can be done, maybe not?

I am using the .NET Core version with EF 6

EFContextProvider.AfterSaveEntities don't receive foreign keys in saveMap that BeforeSaveEntities does.

I've got EF Model and ContextProvider:

public class VObjectLabel
{
    [Key]
    public int Id { get; set; }
    public virtual VObject VObject { get; set; }
    public string VObjectID { get; set; }
}
public class VObject
{
    public VObject()
    {
        SecurityLevelID = 1;
    }
    [Key]
    public string Id { get; set; }
}

public partial class DB : DbContext
{
    public DbSet<VObject> VObjects { get; set; }
    public DbSet<VObjectLabel> VObjectLabels { get; set; }   
}

public class DBModelContextProvider : EFContextProvider<DB>
{
    protected override void AfterSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap, List<KeyMapping> keyMappings)
    {
        base.AfterSaveEntities(saveMap, keyMappings);
    }
    protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap)
    {
        return base.BeforeSaveEntities(saveMap);
    }
}

When i delete something from this contextprovider like this, passing VObjectLabel with the Id and VObjectID filled.

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

BeforeSaveEntities have saveMap with Id and VObjectID filled,
AfterSaveEntities have saveMap with Id filled but VObjectID is empty .

When i change VObject key to int, it is working as expexted, key is in After and Before hooks.

Exception in EFContextProvider.Metadata() when EF model contains ComplexTypes

When we add an SP which returns some columns, i.e. in EF model its return type is represented with a Complex Type, EFContextProvider.Metadata() throws exception:

System.ArgumentException: 'Could not find the CLR type for 'Model.PendingCallListGet_Result'.'

Stack trace:

at System.Data.Entity.Core.Metadata.Edm.MetadataWorkspace.GetObjectSpaceType[T](T edmSpaceType)
at System.Data.Entity.Core.Metadata.Edm.MetadataWorkspace.GetObjectSpaceType(StructuralType edmSpaceType)
at Breeze.ContextProvider.EF6.EFContextProvider1.<>c__DisplayClass56_0.<UpdateCSpaceOSpaceMappingCore>b__1(StructuralType st) in C:\\git\\Breeze\\breeze.server.net\\AspNet\\Breeze.ContextProvider.EF6\\EFContextProvider.cs:line 727 at System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()\r\n at System.Collections.Generic.List1..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at Breeze.ContextProvider.EF6.EFContextProvider1.UpdateCSpaceOSpaceMappingCore(XDocument xDoc, MetadataWorkspace metadataWs) in C:\git\Breeze\breeze.server.net\AspNet\Breeze.ContextProvider.EF6\EFContextProvider.cs:line 724
at Breeze.ContextProvider.EF6.EFContextProvider1.UpdateCSpaceOSpaceMapping(XDocument xDoc, ObjectContext oc) in C:\\git\\Breeze\\breeze.server.net\\AspNet\\Breeze.ContextProvider.EF6\\EFContextProvider.cs:line 697 at Breeze.ContextProvider.EF6.EFContextProvider1.GetMetadataFromObjectContext(Object context) in C:\git\Breeze\breeze.server.net\AspNet\Breeze.ContextProvider.EF6\EFContextProvider.cs:line 614
at Breeze.ContextProvider.EF6.EFContextProvider1.GetMetadataFromDbContext(Object context) in C:\\git\\Breeze\\breeze.server.net\\AspNet\\Breeze.ContextProvider.EF6\\EFContextProvider.cs:line 593 at Breeze.ContextProvider.EF6.EFContextProvider1.GetMetadataFromContext(Object context) in C:\git\Breeze\breeze.server.net\AspNet\Breeze.ContextProvider.EF6\EFContextProvider.cs:line 575
at Breeze.ContextProvider.EF6.EFContextProvider`1.BuildJsonMetadata() in C:\git\Breeze\breeze.server.net\AspNet\Breeze.ContextProvider.EF6\EFContextProvider.cs:line 142
at Breeze.ContextProvider.ContextProvider.Metadata() in C:\git\Breeze\breeze.server.net\AspNet\Breeze.ContextProvider\ContextProvider.cs:line 34

Error Generating Metadata with EF Core 2.1 and Identity

When I attempt to generate metadata I get the below error. I am using EF Core with identity

System.NullReferenceException: Object reference not set to an instance of an object.
   at Breeze.Persistence.EFCore.MetadataBuilder.BuildAssocName(INavigation prop) in C:\git\Breeze\breeze.server.net\AspNetCore\Breeze.Persistence.EFCore\MetadataBuilder.cs:line 138
   at Breeze.Persistence.EFCore.MetadataBuilder.CreateNavProperty(INavigation p) in C:\git\Breeze\breeze.server.net\AspNetCore\Breeze.Persistence.EFCore\MetadataBuilder.cs:line 128
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.ToList()
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Breeze.Persistence.EFCore.MetadataBuilder.CreateMetaType(IEntityType et, Dictionary`2 dbSetMap) in C:\git\Breeze\breeze.server.net\AspNetCore\Breeze.Persistence.EFCore\MetadataBuilder.cs:line 89
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.ToList()
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Breeze.Persistence.EFCore.MetadataBuilder.GetMetadataFromContext(DbContext dbContext) in C:\git\Breeze\breeze.server.net\AspNetCore\Breeze.Persistence.EFCore\MetadataBuilder.cs:line 21
   at Breeze.Persistence.EFCore.EFPersistenceManager`1.BuildJsonMetadata() in C:\git\Breeze\breeze.server.net\AspNetCore\Breeze.Persistence.EFCore\EFPersistenceManager.cs:line 109
   at Breeze.Persistence.PersistenceManager.Metadata() in C:\git\Breeze\breeze.server.net\AspNetCore\Breeze.Persistence\PersistenceManager.cs:line 34
   at MITSBusinessLib.Repositories.EventOrganizerRepo.MetaData() in C:\Users\Jason\Documents\MITSWebApp\MITSBusinessLib\Repositories\EventOrganizerRepo.cs:line 28
   at MITSWebServices.Controllers.EventOrganizerController.Metadata() in C:\Users\Jason\Documents\MITSWebApp\MITSWebServices\Controllers\EventOrganizerController.cs:line 29
   at lambda_method(Closure , Object , Object[] )
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

This is my Context

using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using MITSDataLib.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace MITSDataLib.Contexts
{
    public class MITSContext : IdentityDbContext<User>
    {

        public MITSContext(DbContextOptions<MITSContext> options): base(options)
        {
            //Do I need these with EF CORE?
            //Configuration.ProxyCreationEnabled = false;
            //Configuration.LazyLoadingEnabled = false;
        }
                
        public DbSet<WildApricotEvent> WaEvents { get; set; }
        public DbSet<WildApricotRegistrationType> WaRegistrationTypes { get; set; }
        public DbSet<Tag> Tags { get; set; }
        public DbSet<Speaker> Speakers { get; set; }
        public DbSet<Section> Sections { get; set; }
        public DbSet<Event> Events { get; set; }
        public DbSet<Day> Days { get; set; }
        public DbSet<Person> People { get; set; }

        
    }
}

Nuspec Metadata update needed for Breeze.ContextProvider

Hi,
Quick FYI, the current NuGet package for ASP.NET Breeze.ContextProvider (ver 1.6.5) didnโ€™t get updated to denote that version 9.0 of Newtonsoft.Json is now required. It still has the dependency metadata set to >= 6.0 .

ContexProvider issues with arrays in saveMap

There is in issue with arrays In the JsonToDictionary method of ContextProvider.cs. They are not taken into account.

For instances, I have a property which is a list of strings, when modifying it on the client and than saving it by calling saveChanges, The associated deserialized originalValuesMap's value is null.

Here is my fix:

private Dictionary<String, Object> JsonToDictionary(dynamic json) {
  if (json == null) return null;
  var jprops = ((System.Collections.IEnumerable)json).Cast<JProperty>();
  var dict = jprops.ToDictionary(jprop => jprop.Name, jprop => {
    var val = jprop.Value as JValue;
    if (val != null) {
      return val.Value;
    } 
    else if (jprop.Value as JArray != null){
        return jprop.Value as JArray;
    }
    else{
        return jprop.Value as JObject;
    }
  });
  return dict;
}

Thanks

Any plans for Typescript Definition generator for the Breeze dbcontext?

For .net it would be really great to an a typescript adapter on the server that creates .d.ts files and places them in a folder of your choice. (Development mode only of course)
So it happens like a the metadata but the the adapter would write the definition to a files to a path of your choice
I did this thing to write out metadata so i could cache it.
But a similar thing could be done with the .d.ts files.

    internal static void WriteContextMetadata<CONTROLLER>(string name) where CONTROLLER : IMetaController, new()
        {
            var metadata = new CONTROLLER().Metadata();

            // construct the filename and runtime file location
            var fileName = HostingEnvironment.MapPath("~/meta/" + name + "Metadata.js");

            // the same pre- and post-fix strings we used earlier
            string prefix = "window." + name +  "BreezeMetadata = JSON.stringify(";

            const string postfix = ");";

            // write to file
            using (var writer = new StreamWriter(fileName))
            {
                writer.WriteLine(prefix + metadata + postfix);
            }
        }

But have the actual types would be stupefyingly awesome.

NHibernate mapping "set of strings" leads to "Not an association"

Breeze.ContextProvider.NH:
The following NHibernate mapping throws an NHibernate.AssertionFailure "Not an association":

set name="Zugnummern"
table="USER_ZUGNUMMER_T"
lazy="true"
cascade="save-update"
key column="USER_ID"
element column="TRAIN_NO"
type="string"
length="6"
not-null="true"
unique="false"

I made a proposal for a fix in NHMetadataBuilder.MakeAssociationProperty of project Breeze.ContextProvider.NH.

Breeze.ContextProvider modified to allow overriding CreateEntityInfoFromJson

Thanks for such fantastic software.

Apologies if this is not possible or represents a really bad idea from an architecture point of view. I would like to quickly and easily be able to map from a Dto to the corresponding server-model object before saving. It is worth noting the example projects referenced in the help documentation and hosted on GitHub demonstrates mapping objects to the DTO, but mapping back is marked as Todo: transform entities in saveBundle from DTO form into server-model form..

The easiest way I can see to do this (glancing at the relevant code) would be something like (untested code):

class MyContextProvider : EFContextProvider<MyDbContext>
{
    protected override  EntityInfo CreateEntityInfoFromJson(JTokenReader tokenReader, Type entityType)
    {
        var entityInfo = base.CreateEntityInfoFromJson(tokenReader, entityType);
        entityInfo.Entity= MapFromDto(entityInfo.Entity);
        return entityInfo;
    }
    private static object MapFromDto(object obj)
    {
        Type t = obj.GetType();
        if (t == typeof(DtoCustomer))
        {
              DtoCustomer customer = (DtoCustomer)entityInfo;
              return new DatabaseCustomer { Id = customer.Id .... };
        }
        return obj;
    }
}

In order to do things this way, it would be necessary for the ContextProvider.CreateEntityInfoFromJson method:

  1. to be marked virtual
  2. to have at least 1 method signature without dynamic arguments, e.g.
    protected internal EntityInfo CreateEntityInfoFromJson(dynamic jo, Type entityType) {
         return CreateEntityInfoFromJson(new JTokenReader(jo), entityType);
    }
    protected internal virtual EntityInfo CreateEntityInfoFromJson(JTokenReader reader, Type entityType) {

Is this an appropriate change to make? Are there better suggestions?

Thank you.

Selecting nullable navigation propery results in server error

Hello,

Suppose I have the following (simplified) Entity model:

public class Invoice 
{
   public int Id { get; set }
   public int CustomerId { get; set; }   <= not nullable
   public int? CategorieId { get; set; }  <= nullable!
   public virtual Customer Customer
   public virtual Category Category
   //much more properties...
}
public class Customer
{
   public int Id { get; set; }
   public string Name { get; set }
}
public class InvoiceType
{
   public int Id { get; set; }
   public string Title{ get; set }
}

When I query this with Breeze server and Breeze Javascript client like this:

let q = new breeze.EntityQuery()
   .from('Invoices')
   .select('Customer.Name')

it works perfectly alright.

However, when I select a nullable column/property, e.g.

let q = new breeze.EntityQuery()
   .from('Invoices')
   .select('Category.Title')

and hit a row without an InvoiceType a server error occurs:

System.InvalidOperationException: The cast to value type 'InvoiceType' failed 
because the materialized value is null. Either the result type's generic parameter or 
the query must use a nullable type.

I can reproduce this behaviour in a Linqpad query: Invoices.Select(x => new { x.Id, x.InvoiceType .Title }) will result in an error for rows without InvoiceType.

However, in Linqpad I can easily fix this: Invoices.Select(x => new { x.Id, Title = x.InvoiceType == null ? null : x.InvoiceType.Title })

I can't do this on the client...

Is this some kind of edge case, or a bug maybe?

I'm using the Core version of Breeze server.

orderby, top , filters not working

I'm trying to use Breeze with ASP.NET Core and Full Entity Framework

My issue is when I call this api:
http://localhost:50969/breeze/Students?$orderby=Id&$top=3&$inlinecount=allpages

this message return to me:
"This EntityQuery ctor requires a valid json string. The following is not json: $orderby=Id"
{ $id: "2", $type: "Breeze.AspNetCore.ErrorDto, Breeze.AspNetCore.NetFramework", Code: 0, Message: "This EntityQuery ctor requires a valid json string. The following is not json: $orderby=Id", StackTrace: " at Breeze.Core.EntityQuery..ctor(String json) at Breeze.AspNetCore.BreezeQueryFilterAttribute.OnActionExecuted(ActionExecutedContext context) at Microsoft.AspNetCore.Mvc.Filters.ActionFilterAttribute.<OnActionExecutionAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextActionFilterAsync>d__25.MoveNext() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeNextExceptionFilterAsync>d__24.MoveNext()", EntityErrors: null }
but when I call the same api without parameters its works fine and returns json like this:
[ { $id: "3", $type: "funny2.Data.Models.Student, funny2.Data", ID: 1, LastName: "Ali", FirstMidName: "Sami", EnrollmentDate: "2017-06-23T23:28:52.873", Enrollments: null } ]

Is there any sample working fine on ASP.NET Core

$select backdoor to expand despite AllowedQueryOptions.Expand set to false

I am finally getting around to using the EnableBreezeQuery as described in #12, but I'm having an issue.

I've set the options to disable expand, so as expected, if I call: orders?$expand=privateObject, I'll get the expected error:

{
  "$id":"1",
  "$type":"System.Web.Http.HttpError, System.Web.Http",
  "Message":"The query specified in the URI is not valid. Query option 'Expand' is not allowed. To allow it, set the 'AllowedQueryOptions' property on EnableQueryAttribute or QueryValidationSettings.",
  "ExceptionMessage":"Query option 'Expand' is not allowed. To allow it, set the 'AllowedQueryOptions' property on EnableQueryAttribute or QueryValidationSettings.",
  "ExceptionType":"Microsoft.Data.OData.ODataException",
  "StackTrace":"   at System.Web.Http.OData.Query.Validators.ODataQueryValidator.ValidateQueryOptionAllowed(AllowedQueryOptions queryOption, AllowedQueryOptions allowed)\r\n   at System.Web.Http.OData.Query.Validators.ODataQueryValidator.Validate(ODataQueryOptions options, ODataValidationSettings validationSettings)\r\n   at System.Web.Http.OData.EnableQueryAttribute.ValidateQuery(HttpRequestMessage request, ODataQueryOptions queryOptions)\r\n   at Breeze.WebApi2.EnableBreezeQueryAttribute.ValidateQuery(HttpRequestMessage request, ODataQueryOptions queryOptions)\r\n   at System.Web.Http.OData.EnableQueryAttribute.ExecuteQuery(Object response, HttpRequestMessage request, HttpActionDescriptor actionDescriptor)\r\n   at System.Web.Http.OData.EnableQueryAttribute.OnActionExecuted(HttpActionExecutedContext actionExecutedContext)"
}

However, if I just call: orders?$select=privateObject, the privateObject will be returned. It looks like you can by pass the expand restriction by just use $select

Critical bug: JSON Date format will vary with browser "Accept-Language" request header

In the latest NuGet package Breeze.Server.ContextProvider (1.6.6), in the method Breeze.ContextProvider.BreezeConfig.CreateJsonSerializerSettings(), the format string currently used for the IsoDateTimeConverter will cause DateTime and DateTimeOffset values to serialize differently with different "Accept-Language" request header values to BreezeControllers:

      jsonSerializerSettings.Converters.Add(new IsoDateTimeConverter {
        DateTimeFormat = "yyyy-MM-dd\\THH:mm:ss.fffK"
        // DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"
      });

Different cultures use different separator characters between year/month/day and hours/minutes/seconds.
The problem with the format string in your code is that the IsoDateTimeConverter interprets dash and colon characters as special placeholder symbols to be replaced with the locale specific separators. Locale seems to be decided by the "Accept-Language" request header (not by Thread.CurrentThread.CurrentCulture which I believed to be the case initially, since ASP.NET by default automatically sets this by parsing the "Accept-Language" request header).

If you test an ASP.NET WebApi2 Breeze Controller with a browser where language is set to f.ex. "Norwegian bokmรฅl", the "Accept-Language" request headers will be "nb-NO", and all dates in the JSON data returned from the controller will be wrong, culture relative, non-ISO-8601-compliant, since the hours/minutes/seconds separator for Norway is '.' (notice the period character used as time separator):

2018-02-21T17.05.00.000+00:00

To use non-culture-relative separators in the IsoDateTimeConverter format string, you need to put single-quotes around them.

The correct format for ISO-8601 date format (with only 3 second fraction digits to support IE9) should be:

"yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFK"

Please fix this as soon as possible and release a new version of the NuGet package - this is a current production issue in our product. We have found a temporary workaround, but this is clearly a bug on your end.

TransactionScope use with NHContext

We use breeze with NHibernate and Oracle.
As recommended in the doc, we set TransactionType to TransactionType.DbTransaction.
We set enlist=true in the connectionstring.
But now, we also use NServicebus. In order to have both msmq and db in the same transaction, we changed TransactionType to TransactionType.TransactionScope.
Out of the box, it didn't work throwing this exceptionConnection is already part of a local or a distributed transaction.
To make it work, I removed the code related to transaction inside NHContext. I don't know exactly what it was supposed to do, as this code is already part of the transaction started in the ContextProvider. The code is still needed if no TransactionSettings is set(None).
Now it works, with both types of Transactions.
Do you see any issues with that?

NB: setting enlist=dynamic seems to work with the initial code. BUT, if an exception occurs the data are not rollbacked. Looking at Oracle docs, dynamic means you have to enlist the transaction by yourself. So it's not the solution

NB2: The changes works well... but we're also using envers and it works only with Oracle and not with Sql Server

NB3: The issue spans over breeze and nhibernate... I'll try to see with NHibernate people what's the best solution

Applying Client Query in Controller

Is there anyway to apply the user query in the controller in order to perform some actions to the final result set?

Take the following example:

[HttpGet]
public IQueryable<Container> Containers(bool populate)
{
    var containers = _contextProvider.Context.Containers;
    if (populate)
    {
         foreach (var container in containers)
         {
             container.Populate(_contextProvider.Context);
         }
    }
    return containers;
}

The problem here is that I am doing this Populate() action to all records in this table instead of just the ones that the user requested because their query has not been applied yet. How can I achieve this?

Please see StackOverflow question here.

Support for OData on ASP.Net Core

More of heads up - as of yesterday, there are now concrete steps in the form of a alpha release for supporting OData on top of ASP.Net Core.

See this comment OData/WebApi#229 (comment)

It would be good to get this on the roadmap for Breeze as part of the ASP.Net core support you are adding.

Using Breeze in Core web application targeting Full Framework

Dear breeze folks,

The beautiful breeze technology seems to be losing some momentum, but I think it can still add great value in this age of browser oriented application development. A vital step for survival is certainly support for the new .NET Core stack.

Since Entity Framework Core is not yet complete, any serious application needs EF6 anyway. So for starters we might as well use a Core web application targeting the Full Framework.

When I try to add Breeze, a number of things work, some do not. This is what I tried:

Override the default context provider to create the DbContext with a connectionstring (should be placed in setting later on)

public class EfContextProvider : EFContextProvider<MyDbContext>
{
	protected override MyDbContext CreateContext()
	{
		return new MyDbContext("connection string");
	}
}

In Startup.cs

public void ConfigureServices(IServiceCollection services)
{
	// other services ommited

	services.AddScoped<EfContextProvider>(_ => new EfContextProvider());
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
	// other middleware ommitted

	app.UseMvc(routes =>
	{
		routes.MapRoute("BreezeApi", "breeze/{controller}/{action}");
	});
}

In project.json

{
  "dependencies": {
    "Microsoft.AspNetCore.Mvc": "1.0.0",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
    "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
    "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
    "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
    "Microsoft.Extensions.Configuration.Json": "1.0.0",
    "Microsoft.Extensions.Logging": "1.0.0",
    "Microsoft.Extensions.Logging.Console": "1.0.0",
    "Microsoft.Extensions.Logging.Debug": "1.0.0",
    "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",

    "EntityFramework": "6.1.3",
    "Breeze.Server.WebApi2": "1.5.5",
    "Breeze.Server.ContextProvider.EF6": "1.5.5"
  },

  "frameworks": {
	"net452": {
		"dependencies": {
			"project containing dbcontext": {
				"target": "project"
			}
		}
	}
  },

//other sections omitted

}

Finally a Breeze controller

[BreezeController]
public class BreezeController : Controller
{
	EfContextProvider contextprovider;
	public BreezeController(EfContextProvider contextprovider)
	{
		this.contextprovider = contextprovider;
	}

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

	[HttpGet]
	[EnableBreezeQuery]
	public IQueryable<Person> Persons()
	{
		return contextprovider.Context.Persons;
	}
}

The metadata is produced OK, and /breeze/persons produces json with Persons.

The problem is that all of the query string parameters like $filter, $top etc seem to be ignored. It seems as something goes wrong with the translation to the Odata layer.

Maybe this just a dead end and I should wait for the final porting, but I have the impression that is can fixed quite easy?

AspnetCore no ODataQueryOptions, how to expand Automapper?

I am attempting to use Automapper to use DTOs in the Aspnet Core version of Breeze. The difficulty I'm am facing right now is that I can't use expand. If I do, it won't generate a good query and I get an error.

The aspnet classic (?) approach using ODataQueryOptions doesn't seem to be an option now because of the decoupling from OData.

Link 1
Link 2

Is there a way to get this information so I can pass it along to automapper, or is this more of a feature request?

Error when query with parameters (breeze.sharp call breeze.server.net - Asp.Net Core/EF Core)

Hello,

I have faced a problem when using breeze.sharp and breeze.server.net - Asp.Net Core + EF Core.

Everything works well when query the full list (http://localhost:5678/breeze/share/companies).
But when I add parameter (http://localhost:5678/breeze/share/companies?$filter=TagName%20eq%20%27DHL%27)
I get error:

{"$id":"32","$type":"Breeze.AspNetCore.ErrorDto, Breeze.AspNetCore.NetCore","Code":0,"Message":"This EntityQuery ctor requires a valid json string. The following is not json: $filter=TagName eq 'DHL'","StackTrace":" at Breeze.Core.EntityQuery..ctor(String json) in D:\GitHub\Breeze\breeze.server.net\AspNetCore\Breeze.Core\Query\EntityQuery.cs:line 37\r\n at Breeze.AspNetCore.BreezeQueryFilterAttribute.OnActionExecuted(ActionExecutedContext context) in D:\GitHub\Breeze\breeze.server.net\AspNetCore\Breeze.AspNetCore.NetCore\QueryFilter.cs:line 33\r\n at Microsoft.AspNetCore.Mvc.Filters.ActionFilterAttribute.OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()\r\n at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextExceptionFilterAsync()","EntityErrors":null}

Try to debug deeper the source code of breeze.server.net and found the error happens in file JsonHelper.cs at line 12........... JToken.parse(json).....

Unable to create the JToken from the query string.

Please help....

ASP.NET 5

Are there any plans to migrate to ASP.NET 5 and EF7 (vNext) in the future?

EnableQuery Attribute trashes paging

This may not be for you but to do with EF but I wonder if you have experienced it.

If I apply an EnableQuery attribute to an endpoint (eq to specify max take count &c although this one is empty..)

[EnableQuery()]
        [HttpGet]
        public IQueryable<HistoryDataLogNodeValue> DataLogNodeValues() { return _context.Context.DataLogNodeValues; }

then paging stops working

here is the sql generated when the enablequery attribute is present

exec sp_executesql N'SELECT TOP (@p__linq__5) 
    [Project2].[row_number] AS [row_number], 
    [Project2].[Id] AS [Id], 
    [Project2].[Value] AS [Value], 
    [Project2].[UnitNodeId] AS [UnitNodeId], 
    [Project2].[RuntimeId] AS [RuntimeId], 
    [Project2].[IsCurrent] AS [IsCurrent], 
    [Project2].[MyCommandId] AS [MyCommandId], 
    [Project2].[Timestamp] AS [Timestamp], 
    [Project2].[CreatedOn] AS [CreatedOn], 
    [Project2].[ModifiedOn] AS [ModifiedOn], 
    [Project2].[UserIdCreated] AS [UserIdCreated]
    FROM ( SELECT [Project2].[Id] AS [Id], [Project2].[Value] AS [Value], [Project2].[UnitNodeId] AS [UnitNodeId], [Project2].[RuntimeId] AS [RuntimeId], [Project2].[IsCurrent] AS [IsCurrent], [Project2].[MyCommandId] AS [MyCommandId], [Project2].[Timestamp] AS [Timestamp], [Project2].[CreatedOn] AS [CreatedOn], [Project2].[ModifiedOn] AS [ModifiedOn], [Project2].[UserIdCreated] AS [UserIdCreated], row_number() OVER (ORDER BY [Project2].[Value] DESC) AS [row_number]
        FROM ( SELECT 
            [Limit1].[Id] AS [Id], 
            [Limit1].[Value] AS [Value], 
            [Limit1].[UnitNodeId] AS [UnitNodeId], 
            [Limit1].[RuntimeId] AS [RuntimeId], 
            [Limit1].[IsCurrent] AS [IsCurrent], 
            [Limit1].[MyCommandId] AS [MyCommandId], 
            [Limit1].[Timestamp] AS [Timestamp], 
            [Limit1].[CreatedOn] AS [CreatedOn], 
            [Limit1].[ModifiedOn] AS [ModifiedOn], 
            [Limit1].[UserIdCreated] AS [UserIdCreated]
            FROM ( SELECT TOP (@p__linq__2) [Project1].[Id] AS [Id], [Project1].[Value] AS [Value], [Project1].[UnitNodeId] AS [UnitNodeId], [Project1].[RuntimeId] AS [RuntimeId], [Project1].[IsCurrent] AS [IsCurrent], [Project1].[MyCommandId] AS [MyCommandId], [Project1].[Timestamp] AS [Timestamp], [Project1].[CreatedOn] AS [CreatedOn], [Project1].[ModifiedOn] AS [ModifiedOn], [Project1].[UserIdCreated] AS [UserIdCreated]
                FROM ( SELECT [Project1].[Id] AS [Id], [Project1].[Value] AS [Value], [Project1].[UnitNodeId] AS [UnitNodeId], [Project1].[RuntimeId] AS [RuntimeId], [Project1].[IsCurrent] AS [IsCurrent], [Project1].[MyCommandId] AS [MyCommandId], [Project1].[Timestamp] AS [Timestamp], [Project1].[CreatedOn] AS [CreatedOn], [Project1].[ModifiedOn] AS [ModifiedOn], [Project1].[UserIdCreated] AS [UserIdCreated], row_number() OVER (ORDER BY [Project1].[Value] DESC, [Project1].[Id] ASC) AS [row_number]
                    FROM ( SELECT 
                        [Extent1].[Id] AS [Id], 
                        [Extent1].[Value] AS [Value], 
                        [Extent1].[UnitNodeId] AS [UnitNodeId], 
                        [Extent1].[RuntimeId] AS [RuntimeId], 
                        [Extent1].[IsCurrent] AS [IsCurrent], 
                        [Extent1].[MyCommandId] AS [MyCommandId], 
                        [Extent1].[Timestamp] AS [Timestamp], 
                        [Extent1].[CreatedOn] AS [CreatedOn], 
                        [Extent1].[ModifiedOn] AS [ModifiedOn], 
                        [Extent1].[UserIdCreated] AS [UserIdCreated]
                        FROM [dbo].[HistoryDataLogNodeValues] AS [Extent1]
                        WHERE [Extent1].[UnitNodeId] = @p__linq__0
                    )  AS [Project1]
                )  AS [Project1]
                WHERE [Project1].[row_number] > @p__linq__1
                ORDER BY [Project1].[Value] DESC, [Project1].[Id] ASC
            )  AS [Limit1]
            WHERE [Limit1].[UnitNodeId] = @p__linq__3
        )  AS [Project2]
    )  AS [Project2]
    WHERE [Project2].[row_number] > @p__linq__4
    ORDER BY [Project2].[Value] DESC',N'@p__linq__0 int,@p__linq__1 int,@p__linq__2 int,@p__linq__3 int,@p__linq__4 int,@p__linq__5 int',@p__linq__0=1,@p__linq__1=10,@p__linq__2=10,@p__linq__3=1,@p__linq__4=10,@p__linq__5=10
go

and here when it is absent

exec sp_executesql N'SELECT TOP (@p__linq__2) 
    [Project1].[Id] AS [Id], 
    [Project1].[Value] AS [Value], 
    [Project1].[UnitNodeId] AS [UnitNodeId], 
    [Project1].[RuntimeId] AS [RuntimeId], 
    [Project1].[IsCurrent] AS [IsCurrent], 
    [Project1].[MyCommandId] AS [MyCommandId], 
    [Project1].[Timestamp] AS [Timestamp], 
    [Project1].[CreatedOn] AS [CreatedOn], 
    [Project1].[ModifiedOn] AS [ModifiedOn], 
    [Project1].[UserIdCreated] AS [UserIdCreated]
    FROM ( SELECT [Project1].[Id] AS [Id], [Project1].[Value] AS [Value], [Project1].[UnitNodeId] AS [UnitNodeId], [Project1].[RuntimeId] AS [RuntimeId], [Project1].[IsCurrent] AS [IsCurrent], [Project1].[MyCommandId] AS [MyCommandId], [Project1].[Timestamp] AS [Timestamp], [Project1].[CreatedOn] AS [CreatedOn], [Project1].[ModifiedOn] AS [ModifiedOn], [Project1].[UserIdCreated] AS [UserIdCreated], row_number() OVER (ORDER BY [Project1].[Value] DESC) AS [row_number]
        FROM ( SELECT 
            [Extent1].[Id] AS [Id], 
            [Extent1].[Value] AS [Value], 
            [Extent1].[UnitNodeId] AS [UnitNodeId], 
            [Extent1].[RuntimeId] AS [RuntimeId], 
            [Extent1].[IsCurrent] AS [IsCurrent], 
            [Extent1].[MyCommandId] AS [MyCommandId], 
            [Extent1].[Timestamp] AS [Timestamp], 
            [Extent1].[CreatedOn] AS [CreatedOn], 
            [Extent1].[ModifiedOn] AS [ModifiedOn], 
            [Extent1].[UserIdCreated] AS [UserIdCreated]
            FROM [dbo].[HistoryDataLogNodeValues] AS [Extent1]
            WHERE [Extent1].[UnitNodeId] = @p__linq__0
        )  AS [Project1]
    )  AS [Project1]
    WHERE [Project1].[row_number] > @p__linq__1
    ORDER BY [Project1].[Value] DESC',N'@p__linq__0 int,@p__linq__1 int,@p__linq__2 int',@p__linq__0=1,@p__linq__1=10,@p__linq__2=10
go

I am using EF6.1.1 and Microsoft.AspNet.WebApi.OData v 5.2.0

.NET Core QueryFilter issue when inner query contains '&'

There's an issue with QueryFilter when it tries to decode a query string with inner contents containing an ampersand (&), e.g.

?{"where":{"CompanyName":{"contains":"Bob&Larry's Garage"}}}?anotherParameter=1

The ExtractAndDecodeQueryString method in QueryFns finds the first instance of an '&' in the query string and cuts off everything after that first instance, which I assume is to remove any additional parameters, such as 'anotherParameter' above. However, given the example above, it returns:

?{"where":{"CompanyName":{"contains":"Bob

QueryFilter blows up a few lines later when it passes this string to the EntityQuery constructor, which tries to deserialize the above as json.

Also, escaping the '&' doesn't really get us anywhere as there's no place where it is un-escaped.

Project dead?

Is the project dead?

Are there any plans to support the new asp.net core?

Please help with brief steps to get ASP.Net Core breeze server up

It would be extremely helpful to get a list of steps to get an ASP.Net Core Breeze server up, even if a full sample is a bit further away.

BTW, this maybe just me, but sometimes a series of step-by-step instructions are far more instructive than code samples...I found Brian Noyes' Pluralsight video far more helpful than the temphire sample.

random slow performance

I have been experiencing slow performance randomly. A slow request is happening perhaps once out of 100 requests. The requests before that, and after that are just fine. It's also not the first request so it can't be initialization of entity framework. The request and the response do not change.

Imgur

In this screenshot I used the Postman chrome plugin to reproduce this. I see the same thing when I call the API from my website.I am using the .net client of Breeze with EF6.1.3 and Web API 2. Any idea how I can troubleshoot this?

XML comment files missing from NuGet packages

The C# Breeze source has many wonderful XML comments adorning its types, methods, etc. The C# compiler happily creates a XML file (a la Breeze.ContextProvider.xml, assuming generation is enabled and using the defaults), which causes the documentation to show up directly in Visual Studio IntelliSense and metadata.

Alas, the NuGet packages don't include the .xml files. Including them would be a fine productivity boost for little effort.

Documentation for .Net Core

There doesn't seem to be any documentation on using Breeze with .Net Core outwith the github issues. I have managed to coax it into life by inspecting efforts by others. I appreciate that it's yet to make v1.0 but there are some significant changes and little guidance as to how to use in a .Net Core app.

ContextProvider Issue(s)

In ContextProvider, Before Save Adding Entity into the SaveMap when none in the list. Specifically when BeforeSaveEntity returns false because it's performed it's own save and the aftersave will update the SaveMap returned to the client.

Added " if (entityInfos.Count > 0) " in the below block.

    public void BeforeSave() {
      SaveMap = new Dictionary<Type, List<EntityInfo>>();
      EntitiesWithAutoGeneratedKeys = new List<EntityInfo>();
      EntityInfoGroups.ForEach(eg => {
        var entityInfos = eg.EntityInfos.Where(ei => ContextProvider.BeforeSaveEntity(ei)).ToList();
        EntitiesWithAutoGeneratedKeys.AddRange(entityInfos.Where(ei => ei.AutoGeneratedKey != null));
        if (entityInfos.Count > 0)  // <-----ADDED
            SaveMap.Add(eg.EntityType, entityInfos);
      });
      SaveMap = ContextProvider.BeforeSaveEntities(SaveMap);
    }

In EF6 ContextProvider, GetEntitySetName(entityType) should be inside the foreach.
Having issues passing back custom DTO's that I will provide my own SaveMap for so the js client's compare can satisfy HasChanges. (The above fix, masks this issue, because the Zero Count list is no longer in the Dictionary, but there is no point to look up types for empty lists )

Moved "GetEntitySetName(..." inside foreach

    private List<EFEntityInfo> ProcessSaves(Dictionary<Type, List<EntityInfo>> saveMap) {
      var deletedEntities = new List<EFEntityInfo>();
      foreach (var kvp in saveMap) {
        var entityType = kvp.Key;
        foreach (EFEntityInfo entityInfo in kvp.Value) {
          var entitySetName = GetEntitySetName(entityType);  // <-  Moved inside foreach
          // entityInfo.EFContextProvider = this;  may be needed eventually.
          entityInfo.EntitySetName = entitySetName;
          ProcessEntity(entityInfo);
          if (entityInfo.EntityState == BreezeCp.EntityState.Deleted) {
            deletedEntities.Add(entityInfo);
          }
        }
      }
      return deletedEntities;
    }

Hope both the above work their way back into the codebase, trying to avoid forking

Thanks, and Great Work!
Mike

Nullable ID fixup resulting in a server error

Hi,
Suppose I have the following model:

public class User{
    public string Name {get;set;}
    public int? ImageId {get;set}
    public Image Image {get;set;}
}

and

public class Image {
    public string Url {get;set;}
}

On the client side, create a new image entity, assign it to a user entity, delete the image then save changes results in the following:

  • The newly created then deleted image isn't part of the save bundle as it was detached [Expected]
  • User.ImageId is still pointing to the image which was deleted. A negative FK [Not Expected]

The save results in a server error as User.ImageId is pointing to a non existing entity.

Is there a specific release date for aspnetcore?

I use vs2017 to create a jumpstart web application project, but when i try to install the Breeze.Server.AspNetCore.NetFramework from nuget, I get the follow errors:

Restoring packages for D:\work\Projects\atom-jumpstart-net\Jumpstart.Web\Jumpstart.Web.csproj...
Package Breeze.Server.AspNetCore.NetFramework 0.1.3 is not compatible with netcoreapp1.0 (.NETCoreApp,Version=v1.0). Package Breeze.Server.AspNetCore.NetFramework 0.1.3 supports: net (.NETFramework,Version=v0.0)
Package Breeze.Server.Core 0.1.3 is not compatible with netcoreapp1.0 (.NETCoreApp,Version=v1.0). Package Breeze.Server.Core 0.1.3 supports: net (.NETFramework,Version=v0.0)
Package Breeze.Server.Persistence 0.1.3 is not compatible with netcoreapp1.0 (.NETCoreApp,Version=v1.0). Package Breeze.Server.Persistence 0.1.3 supports: net (.NETFramework,Version=v0.0)
One or more packages are incompatible with .NETCoreApp,Version=v1.0.
Package restore failed. Rolling back package changes for 'Jumpstart.Web'.

Breeze Assemblies for .Net Core 2.0

I am using the following libraries in my Project

Breeze.Angular.1.1.1
Breeze.Angular.Directives.1.3.10
Breeze.Client.1.5.5
Breeze.Server.ContextProvider.1.5.0
Breeze.Server.ContextProvider.1.6.0
Breeze.Server.ContextProvider.EF6.1.5.0
Breeze.Server.ContextProvider.EF6.1.6.0
Breeze.Server.WebApi2.1.6.0

what's the equivalent libraries for .Net Core for the above that I am using in .Net Framework 4.7.1

EFContextProvider 1.4.16 throws DbUpdateConcurrencyException when trying to update Enum value.

Trying to SaveChanges of a single enum property value update throws System.Data.Entity.Infrastructure.DbUpdateConcurrencyException.

The enum property is defined like this:

        public virtual System.Nullable<StanZleceniaOplaty> Stan { get; set; }

        public enum StanZleceniaOplaty : int
        {
                    Created,
                    Started,
                    Canceled,
                    Rejected,
                    Paid
        }

EntityTypeConfiguration for entity ZlecenieOplaty configures Stan with the following code:

        this
            .Property(p => p.Stan)
                .IsConcurrencyToken()
                .HasColumnType("int"); 

I can see that the SQL generated by EFContextProvider agains the EF 6.1 DB is wrong ([Stan] is not changed, because @0 == @2, @2 has wrong value - should be 0).

exec sp_executesql N'UPDATE [dbo].[ZlecenieOplaty]
SET [Stan] = @0
WHERE (([Id] = @1) AND ([Stan] = @2))
SELECT [NrZlecenia]
FROM [dbo].[ZlecenieOplaty]
WHERE @@ROWCOUNT > 0 AND [Id] = @1',
N'@0 int,@1 int,@2 int',
@0=2,
@1=3,
@2=2

In effect the following exception is thrown.

System.Data.Entity.Infrastructure.DbUpdateConcurrencyException occurred
  HResult=-2146233087
  Message=Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
  Source=EntityFramework
  StackTrace:
       at System.Data.Entity.Internal.InternalContext.SaveChanges()
       at Alcance.Entities.AlcanceDbContext.SaveChanges() in d:\Develop\alcance\src\dev\Alcance.Data\Model\AlcanceModel.AlcanceDbContext.Connection.cs:line 121
  InnerException: System.Data.Entity.Core.OptimisticConcurrencyException
       HResult=-2146233087
       Message=Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
       Source=EntityFramework
       StackTrace:
            at System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.ValidateRowsAffected(Int64 rowsAffected, UpdateCommand source)
            at System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.Update()
            at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
            at System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(SaveOptions options, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction)
            at System.Data.Entity.Infrastructure.DbExecutionStrategy.Execute[TResult](Func`1 operation)
            at System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions options, Boolean executeInExistingTransaction)
            at System.Data.Entity.Internal.InternalContext.SaveChanges()
       InnerException:

Option to disable Expand options

It would be nice to disable the expand option for purposes of security. As it is, we cannot directly expose the db context, instead we must use toList which impacts performance.

Breeze still suggested for greenfield projects?

Hi thanks for all the work on breeze, I've used it on so many projects alongside .net full framework.

Now, I'm starting on some rather large greenfield projects, and noticed that activity has died down considerably on stackoverflow, and updates to breeze library in general (temphire demo app, etc.)

This could very well be because breezejs is now considered mature and stable and doesn't need a lot of fixes because everything pretty much works very reliably.

I just would like to know before beginning these new projects...would breeze still be the go-to recommended project for greenfield these days, or is it winding down because breeze developers (users and/or contributors) are moving to other things, like graphql?

Again, thanks for all the work over the years this project has been a game-changer for my past projects.

Use TypeNameHandling None for DynamicTypes

When you are doing a select projection, the serialized Json has a long $type property. For example:

"$type":"_IB_w3cYOcY0lxw2mLrFH_pc88Gzr_dks[[System.Guid, mscorlib]], _IB_w3cYOcY0lxw2mLrFH_pc88Gzr_dks_IdeaBlade"

For large collections, this adds a large overhead to the call, especially when you are only pulling one or two properties off of the objects. It would be much nicer to use TypeNameHandling = None for DynamicTypes. Even better would be to somehow put the $type on the array if all items have the same type.

DateTimeOffsetConverter cannot convert from System.DateTime

Message=DateTimeOffsetConverter cannot convert from System.DateTime.
  Source=System
  StackTrace:
       at System.ComponentModel.TypeConverter.GetConvertFromException(Object value)
       at System.ComponentModel.TypeConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
       at System.ComponentModel.DateTimeOffsetConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
       at Breeze.ContextProvider.EF6.EFContextProvider`1.ConvertValue(Object val, Type toType)
       at Breeze.ContextProvider.EF6.EFContextProvider`1.SetPropertyValue(Object entity, String propertyName, Object value)
       at Breeze.ContextProvider.EF6.EFContextProvider`1.RestoreOriginal(EntityInfo entityInfo)
       at Breeze.ContextProvider.EF6.EFContextProvider`1.<ProcessAllDeleted>b__9(EFEntityInfo entityInfo)
       at System.Collections.Generic.List`1.ForEach(Action`1 action)
       at Breeze.ContextProvider.EF6.EFContextProvider`1.ProcessAllDeleted(List`1 deletedEntities)
       at Breeze.ContextProvider.EF6.EFContextProvider`1.SaveChangesCore(SaveWorkState saveWorkState)
       at Breeze.ContextProvider.ContextProvider.OpenAndSave(SaveWorkState saveWorkState)
       at Breeze.ContextProvider.ContextProvider.SaveChanges(JObject saveBundle, TransactionSettings transactionSettings)
       at WaterTrack.WebApi.Breeze.Controllers.BreezeController.SaveChanges(JObject saveBundle) in ...

This error occurs when trying to save changes to an entity that has a DateTimeOffset property and the entityInfo.OriginalValuesMap contains a value for that column. It seems that the when the OriginalValuesMap is parsed into a KVP, a DateTime instead of DateTimeOffset type is used for the value of the column.

Has anyone else run into this?

Expand - SyntaxError: JSON.parse: end of data after property value...

Any help on this wold be greatly appreciated. Using AspNetCore 0.1.2 and ASP.NET Core 2.1.

Whey trying to query with 'expand' I keep getting a version of the following with all entities. For example:

https://localhost:44382/breeze/Accounts?{%22expand%22%3A[%22users%22]}

Error > SyntaxError: JSON.parse: end of data after property value in object at line 1 column 137 of the JSON data

Raw Data > {"results":[{"id":1,"customers":[],"guid":"1601a615-3b57-4f71-a0ff-f060b8467565","name":"OC SCUBA Center","users":[{"id":1,"accountId":1

Here are the entity models for reference:

public class AccountEntity
{
    [Key]
    public int id { get; set; }

    public List<CustomerEntity> customers { get; set; } = new List<CustomerEntity>();

    public Guid guid { get; set; } = Guid.NewGuid();

    [Required]
    [MaxLength(50)]
    public string name { get; set; }

    public List<UserEntity> users { get; set; } = new List<UserEntity>();

    public List<WorkOrderEntity> workOrders { get; set; } = new List<WorkOrderEntity>();
}

public class UserEntity
{
    [Key]
    public int id { get; set; }

    public int accountId { get; set; }
    public AccountEntity account { get; set; }

    [Required]
    public string firstName { get; set; }

    public Guid guid { get; set; } = Guid.NewGuid();

    [Required]
    public string lastName { get; set; }

    [Required]
    public string phone { get; set; }

    [Required]
    public string email { get; set; }

    public List<WorkOrderItemLogEntity> workOrderItemLogs { get; set; } = new List<WorkOrderItemLogEntity>();
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.