With the code below I am having an issue where not all the columns are return data in the data.results array. For example if col4 is null in the database for row 1 then data.results[0] does not contain an element for col4, but row 2 has a value then data.results[1] will contain the value for col4. I would like each return item in the array to contain all items with the database value or null. If null can't be returned then an empty string would do.
var query = new breeze.EntityQuery()
.from('mytable')
.where('col1', 'substringof', '2')
.select('col1,col2,col3,col4')
.orderBy('col1')
.take(200);
return _manager
.executeQuery(query)
.then(function (data) {
return data.results;
})
.fail(queryFailed);
}
By default breeze does not serialize null values in its JSON results. This was a deliberate choice to reduce the breeze payload over the wire. And.. this is not typically an issue with queries that return "entities". i.e. data for which breeze metadata exists. Because the properties are already defined on such entities.
But if you are returning an anonymous result as you are, then this can be a problem. You can obviously work around it because you know the properties that you are requesting and can update them after the query if they are not in the result.
But you can also change breeze's default configuration to accommodate this via the "BreezeConfig" class.
BreezeConfig enables customization of components supporting Breeze-related operations in the Web API. BreezeConfig defines default behaviors; you can substitute your own behaviors by deriving from it and overriding its virtual methods. Breeze.NET will discover your subclass among the assemblies referenced by your project and use it instead of BreezeConfig.
To use BreezeConfig to configure the Json.Net serializer with specific settings. You can replace those settings by writing a subclass of BreezeConfig that overrides the 'CreateJsonSerializerSettings' method as shown in this example:
public class CustomBreezeConfig : Breeze.WebApi.BreezeConfig {
protected override JsonSerializerSettings CreateJsonSerializerSettings() {
var baseSettings = base.CreateJsonSerializerSettings();
baseSettings.NullValueHandling = NullValueHandling.Include;
return baseSettings;
}
Hope this helps.
Related
I am not sure if this is even possible but here's my setup:
I have basically 2 Maps holding a special identifier to get some objects.
these identifier is like a versioning number, i may have data in version 8 that belongs to meta version 5. But at the same time, Meta versions up to 10 may exist and not every meta version holds information about every data, so here's where the _filter kicks in.
The filter is able to find to any given value the correct object. So far so good.
My question belongs to the following: (last codeline)
how am i able to say "if you have no matching candidate, generate me a default value"
For this purpose, i tried to force a named constructor with a super class for "Data" and "Meta" called "BasicInformation".
But even if i implement this, how do i call something like T.namedConstructor(); ?
class Repo{
Map<int, Data> mapData;
Map<int, Meta> mapMeta;
Data getData(int value)
{
return _filter<Data>(mapData, value);
}
Meta getMeta(int value)
{
return _filter<Data>(mapMeta, value);
}
T _filter<T extends BasicInformation>(Map<int, T>, int value)
{
//fancy filtering technique
//....
//speudo code
if (found) return map[found]; //speudo code
else return T.generateDefault();
}
}
I've found the following stackoverflow entry: Calling method on generic type Dart
which says, this is not possible without adding a function call.
I am setting properties in client-side Breeze entities. I see the EntityInfo UnmappedValuesMap collection, which I'd like to use. It would be great if I could get a few custom client values returned in the Unmapped collection to avoid adding these everywhere.
I am initializing the metastore with:
store.registerEntityTypeCtor("UserInfo", null, userInfoInitializer);
function userInfoInitializer(userinfo) {
userinfo.creatingId = ko.observable(0);
...
I was hoping 'creatingId' would get passed to server. But nothing extra appears in the net traffic.
I don't think it matters, but on the server I am using Breeze.ContextProvider.
Are there flags somewhere that govern this behavior? Thanks for any guidance.
If you wanted to add a 'creatingId' to every entity type you could do something like this:
metadataStore.getEntityTypes().forEach(
function(entityType) {
var ctor = function () {
this.creatingId = 0;
};
metadataStore.registerEntityTypeCtor(entityType.name, ctor, null);
});
Note- using a constructor instead of an initializer. This will ensure the value appears in the unmapped values collection. Don't worry, breeze will make this an observable property on your entity.
I've noticed that in the metadata there's an object entityType but also an object enumType.
We use manager.metadataStore.getEntityType() to access the metadata of an Entity.
How can we do it for a given enum ? How would I create the enum on the client side out of the metadata ?
Also, when I assign an enum value to a property, I'd like to to it by name instead of by value.
For instance, assuming that Status is of type myEnum:
myEntity.Status = myEnum.Valid;
instead of
myEntity.Status = 1;
Does breeze have any helper function to access the values of an enum ?
This issue is still open as I write. But you might want to take a look at the work-around described in the answer to this SO question.
I am assuming that you are talking about data properties that are defined as .NET enums on the server, and you want additional metadata about these properties to be made available on the Breeze client.
Unfortunately, Breeze does not yet support any metadata on enum types other than the name of the .NET type backing the enum value. This is the 'enumType' property that will appear on any dataProperty that is backed by an .NET Enum on the server. (We do need to document this better)
Please add a feature request for this to the Breeze User Voice. It's a good idea and we do take these suggestions very seriously.
Well this is not exact solution to your question but definitely can help people who are generating metadata offline.
I am using NancyFx(No EF) + Breeze + AngularJS for my web project and generating breeze metadata offline(using EF methods at development) and then using it in js file.
I also encountered similar situation where I want to get all Enum values to bind dropdowns and to display EnumName corresponding to EnumValue(Id). I searched over net but there was not much as per my scenario.
So I have written raw JS methods
1. To extract all enums and their values(Id & Name) in a JS dictionary(associated array) from metadata.
var enumDictionary = {};
JSON.parse(window.app.metadata).schema.enumType.forEach(function (enumType) {
var newEnumValues = [];
enumType.member.forEach(function (enumValue) {
var newEnumValue = { id: enumValue.value, name: enumValue.name };
newEnumValues.push(newEnumValue);
});
enumDictionary[enumType.name] = newEnumValues;
});
I created a method to get all enum values for a specific enum. This will be used for binding a dropdown.
function GetEnumDictionary(enumName) {
return enumDictionary[enumName];
}
Another method I created to get specific Enum name on basis of value.
function GetEnumDictionaryValue(enumName, enumValueId) {
var result = null;
enumDictionary[enumName].some(function (enumValue) {
if (enumValue.id == enumValueId) {
result = enumValue.name;
return;
}
});
return result;
}
I'm experimenting with BreezeJS with Web API using the BreezeControllerAttribute. How should calculated properties on an entity be exposed? The only way I've found to do this reliably is to create an intermediate DTO that inherits from the entity or use a projection. Normally I would use a readonly property for this scenario, but those appear to be ignored.
When Breeze maps JSON property data to entities, it ignores properties that it does not recognize. That's why your server class's calculated property data are discarded even though you see them in the JSON on the wire.
Fortunately, you can teach Breeze to recognize the property by registering it as an unmapped property. I'll show you how. Let me give some background first.
Background
Your calculated property would be "known" to the Breeze client had it been a property calculated by the database. Database-backed properties (regular and calculated) are picked up in metadata as mapped properties.
But in your case (if I understand correctly) the property is defined in the logic of the server-side class, not in the database. Therefore it is not among the mapped properties in metadata. It is hidden from metadata. It is an unmapped instance property.
I assume you're not hiding it from the serializer. If you look at the network traffic for a query of the class, you can see your calculated property data arriving at the client. The problem is that Breeze is ignoring it when it "materializes" entities from these query results.
Solution with example
The solution is to register the calculated property in the MetadataStore.
I modified the entityExtensionTests.js of the DocCode sample to include this scenario; you can get that code from GitHub or wait for the next Breeze release.
Or just follow along with the code below, starting with this snippet from the Employee class in NorthwindModel.cs:
// Unmapped, server-side calculated property
[NotMapped] // Hidden from Entity Framework; still serialized to the client
public string FullName {
get { return LastName +
(String.IsNullOrWhiteSpace(FirstName)? "" : (", " + FirstName)); }
}
And here is the automated test in entityExtensionTests.js
test("unmapped property can be set by a calculated property of the server class", 2,
function () {
var store = cloneModuleMetadataStore(); // clones the Northwind MetadataStore
// custom Employee constructor
var employeeCtor = function () {
//'Fullname' is a server-side calculated property of the Employee class
// This unmapped property will be empty for new entities
// but will be set for existing entities during query materialization
this.FullName = "";
};
// register the custom constructor
store.registerEntityTypeCtor("Employee", employeeCtor);
var fullProp = store.getEntityType('Employee').getProperty('FullName');
ok(fullProp && fullProp.isUnmapped,
"'FullName' should be an unmapped property after registration");
var em = newEm(store); // helper creates a manager using this MetadataStore
var query = EntityQuery.from('Employees').using(em);
stop(); // going async
query.execute().then(success).fail(handleFail).fin(start);
function success(data) {
var first = data.results[0];
var full = first.FullName();
// passing test confirms that the FulllName property has a value
ok(full, "queried 'Employee' should have a fullname ('Last, First'); it is "+full);
}
});
What you need to do is in this small part of the test example:
var yourTypeCtor = function () {
this.calculatedProperty = ""; // "" or instance of whatever type is is supposed to be
};
// register your custom constructor
store.registerEntityTypeCtor("YourType", yourTypeCtor);
Is there any way to use DataContext to execute some explicit SQL and return the auto-increment primary key value of the inserted row without using ExecuteMethodCall? All I want to do is insert some data into a table and get back the newly created primary key but without using LINQ (I use explicit SQL in my queries, just using LINQ to model the data).
Cheers
EDIT: Basically, I want to do this:
public int CreateSomething(Something somethingToCreate)
{
string query = "MyFunkyQuery";
this.ExecuteCommand(query);
// return back the ID of the inserted value here!
}
SOLUTION
This one took a while. You have to pass a reference for the OUTPUT parameter in your sproc in your parameter list of the calling function like so:
[Parameter(Name = "InsertedContractID", DbType = "Int")] ref System.Nullable<int> insertedContractID
Then you have to do
insertedContractID = ((System.Nullable<int>)(result.GetParameterValue(16)));
once you've called it. Then you can use this outside of it:
public int? CreateContract(Contract contractToCreate)
{
System.Nullable<int> insertedContractID = null; ref insertedContractID);
return insertedContractID;
}
Take heavy note of GetParameterValue(16). It's indexed to whichever parameter it is in your parameter list (this isn't the full code, by the way).
You can use something like this:
int newID = myDataContext.ExecuteQuery<int>(
"INSERT INTO MyTable (Col1, Col2) VALUES ({0}, {1});
SELECT Convert(Int, ##IDENTITY)",
val1, val2).First();
The key is in converting ##IDENTITY in type int, like Ben sugested.
If you insist on using raw sql queries, then why not just use sprocs for your inserts? You could get the identity returned through an output parameters.
I'm not the greatest at SQL, but I broke out LinqPad and came up with this. It's a big hack in my opinion, but it works ... kinda.
DataContext.ExecuteQuery<T>() returns an IEnumerable<T> where T is a mapped linq entity. The extra select I added will only populate the YourPrimaryKey property.
public int CreateSomething(Something somethingToCreate)
{
// sub out your versions of YourLinqEntity & YourPrimaryKey
string query = "MyFunkyQuery" + "select Convert(Int, SCOPE_IDENTITY()) as [YourPrimaryKey]";
var result = this.ExecuteQuery<YourLinqEntity>(query);
return result.First().YourPrimaryKey;
}
You'll need to modify your insert statement to include a SELECT ##Identity (SQL Server) or similar at the end.