Metadata issue with multiple models & Breeze contexts - asp.net-mvc

Has anyone else tried using the server-side component of Breeze.js in a solution with multiple Api Controllers for multiple EF Models?
I'm finding that after calling the MetaData endpoint on one context, all subsequent calls to MetaData endpoints in other contexts return the MetaData from the first context which was called, for example say I have two Api Controllers, each with their own MetaData endpoint:
public class CoreController : ApiController
{
readonly EFContextProvider<CoreEntities> contextProvider = new EFContextProvider<CoreEntities>();
}
public class FormsController : ApiController
{
readonly EFContextProvider<FormsEntities> contextProvider = new EFContextProvider<FormsEntities>();
}
Calling ~/Core/MetaData will return the JSON for the Core model, however a subsequent call to ~/Forms/MetaData will not return the Forms JSON, but instead the Core metadata is returned. If I call them in reverse I get the Forms metadata both times, this issue appears to persist until the host process is recycled.
I can confirm that I am able to access object data from both models as expected, so I doubt this is a routing issue.
Perhaps someone can tell me if there is some caching going on somewhere which I need to disable?
Regards,
Tom Tregenna

Ok, this should be fixed in Breeze 0.73.4, available either via nuget or zips on the breeze website.

You are right. I've tested this issue and this behaviour you reported happened. Putting breakpoints for each Metadata() method for the two Controllers, and using Fiddler, I concluded that this is not a routing issue. The two Controllers are using differents Context (contextProvider's property), but the first Metadata that was called is always returned. I guess this is Breeze's library issue. I've read the Breeze's documentation, but I have not found anything that could help.

There is another issue with the same symptoms. It is related to ambiguous references to the Entity Framework metadata in the connection string. I had two separate EDMX files, both of which were named Model.edmx (separate projects). When I referenced the assembly that contained the second EDMX file, the connection string below became ambiguous - the metadata files from both of the EDMX files fit the description.
metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;
I was able to resolve the issue by renaming one of the EDMX files.
An alternative solution would be to replace the asterisk with the full name of the assembly which contains the embedded metadata - there is actually a performance benefit to doing so. See the MSDN documentation covering Entity Framework connection strings for further details.
assemblyFullName
The full name of an assembly with the embedded resource. The name
includes the simple name, version name, supported culture, and public
key, as follows:
ResourceLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Resources can be embedded in any assembly that is accessible by the
application.
If you specify a wildcard (*) for assemblyFullName, the Entity
Framework runtime will search for resources in the following
locations, in this order:
The calling assembly.
The referenced assemblies.
The assemblies in the bin directory of an application.
If the files are not in one of these locations, an exception will be
thrown.
Cc716756.note(en-us,VS.100).gifNote: When you use wildcard (*), the
Entity Framework has to look through all the assemblies for resources
with the correct name. To improve performance, specify the assembly
name instead of the wildcard.

Related

A circular reference was detected while serializing with Json.Encode

I have situation where Json.Encode is working locally (localhost) which is 64bit iis7 windows 7 box.
If I deploy to windows 2003 32 bit IIS6 I get circular reference errors. Shown below 'Error here' is the line where the error starts.
#*var model = '#Html.Raw(Json.Encode(Model))';*# <<<<Error here
var model = '#Html.GetJson(Model)';
As part of trying to resolve this I thought maybe one of the project dll's that were being used on the server was different than that locally so i copied any reference dll to the server bin directory. This did not help.
I do have a fix which is pretty easy. I would have preferred to be able to identity the issue. My guess is that it is using some dll on the server differently than locally to return json via Json.Encode then on the server.
My resolution as shown 2nd line above is to use Json.Net and a mvc helper
public static MvcHtmlString GetJson(this HtmlHelper htmlHelper, ViewModel vm)
{
string s = JsonConvert.SerializeObject(vm);
return new MvcHtmlString(s);
}
Has anyone seen this and resolved? (without json.net)
Assuming you're using Entity Framework, taking a look at the entities developed by the framework will shed some light on the topic. For example, I had table called Sessions and one called Enrollments, the Enrollments table having an FK relationship to the Sessions table PK. This resulted in the Session objects having a collection of Enrollments, and the Enrollment objects having a virtual instance of the Session that the enrollment was for ... which in turn pointed to a collection of Enrollments etc ... you get the picture, AND why the circular reference issue was detected by the json serialization.
The solution was to NOT query a collection of Session objects in the code, but to query an anonymous (untyped) object with all the same fields in it instead. The prevents the Json.Encode() from getting confused about, since it doesn't know about, the circular reference that Entity Framework is OK with in the code behind / server side code.

Error in Model classes after creating Model.Context and Model classes in ASP.Net MVC 4

I have generated xxxModel.Context and xxxModel template (in Models) from an existing database using EF 4.1 on ASP.Net MVC 4 application. After that when I build the project it gives the error for all the Model classes (POCO) saying "The type file name already contains a definition for memeber variable name". Where am I going wrong?
Thanks for help.
Clearly the file DESE.cs (and others) already contains identically named classes with properties - which are clashing with the types generated by EF. CC_Names.cs, for example, is being output by a text template - so I'm assuming you've got more than one code-generation strategy going on here from the same database.
And then you also have issues where you've re-declared the partial class CorpCostEntities again in another file with a different base to the one set by the EF code generator.
I think you might need to decide whether you want to use edmx code generation or the text-templating approach and stick to it :)

Share a model between multiple edmx files (Entity Framework 4.0)

I am searching for the solution of the problem i am and probably many must be facing.
Curently i am working on a application containing nearly 400 tables.
Application consists of seven Class library projects( StudentInfo, library, Fees etc) and each has its own .edmx file(consisting 50 tables) with code generation strategy=default And
a single web application project which references the class library projects.
There are around 15 tables which are common and will be present in .edmx file in each class library project. The namespace of the classes/models is the same(Campus) in all the .edmx files.
I have created a partial class namely School(which is one of the commom table/model) which contains some methods.
However the following compile time error is thrown
The type 'Campus.School' exists in both 'D:\Project\Campus\CampusStudent\' and 'D:\Project\Campus\CampusLibrary\bin\Debug\CampusLibrary.dll'
The solutions that were suggested by other members
1)Have separate namespaces for each of the .edmx files.
2)Use different names to the models namely StudentSchool, LibrarySchool etc.
Both solutions will force me to duplicate the common classes with its methods in each of the class library projects.
Can anybody help me?
There can be a way if you are using POCO T4 template for current entity generation. POCOs in EF can be any class in any namespace which have the same name as entity in your EDMX and which have all properties with the same name as entity in EDMX (including same types and accessibilities for getters and setters).
Define your 15 shared classes in another assembly (you must follow those mentioned POCO rules) and reference it by all library projects. Once you have this assembly create your own version of POCO T4 template which will not create new class files for those shared entities and instead use classes from referenced assembly.
The other option is manual creation and maintenance of all those 400 classes and EF context types. That is what you will do if you use code only mapping (aka code-first) and you will not have these problems.

Specify Connection string for Entity Framework used from multiple projects

I am currently using EntityFramework 4 with POCO objects. The POCO objects are located in their own .net project (project.Models). The Context is located in the DAL project (project.DAL). I have multiple other projects that I wish to use the context/models, for Example:
project.Website
project.Webservice
project.ConsoleApplication
Question:
How do I set the Context's connection string myself?
I have noticed that the Context object automatically finds the connection string in the web.config of the website if I add it there. Do I need to do something similiar for all the other projects? This seems inelegant and i think i'd rather have a way to manually configure it from my own config file or something.
Thanks!
AFrieze
You can pass a connection string as the first argument to the ObjectContext constructor. Read it from wherever you like and pass it explicitly, if that's what you want.

Using repository pattern in ASP.NET MVC with a SQL Server DB; how to mock repository so its unit testable without breaking OOD

I've been learning the ASP.NET MVC framework using the Apress book "Pro ASP.NET MVC Framework" by Steven Sanderson. To that end I have been trying out a few things on a project that I am not that familar with but are things that I thing I should be doing, namely:
Using repository pattern to access my database and populate my domain/business objects.
Use an interface for the repository so it can be mocked in a test project.
Use inversion of control to create my controllers
I have an MVC web app, domain library, test library.
In my database my domain items have an Id represented as an int identity column. In my domain classes the setter is internal so only the repository can set it.
So my quandries/problems are:
Effectively all classes in the domain library can set the Id property, not good for OOP as they should be read-only.
In my test library I create a fake repository. However since it's a different assembly I can't set the Id properties on classes.
What do others do when using a database data store? I imagine that many use an integer Id as unique identifier in the database and would then need to set it the object but not by anything else.
Can't you set your objects' IDs during construction and make them read-only, rather than setting IDs through a setter method?
Or do you need to set the ID at other times. If that's the case, could you explain why?
EDIT:
Would it be possible to divorce the ID and the domain object? Does anything other than the repository need to know the ID?
Remove the ID field from your domain object, and have your repository implementations track object IDs using a private Dictionary. That way anyone can create instances of your domain objects, but they can't do silly things with the IDs.
That way, the IDs of the domain objects are whatever the repository implementation decides they are - they could be ints from a database, urls, or file names.
If someone creates a new domain object outside of the repository and say, tried to save it to your repository, you can look up the ID of the object and save it as appropriate. If the ID isn't there, you can either throw an exception to say you need to create the object using a repository method, or create a new ID for it.
Is there anything that would stop you from using this pattern?
you can use the InternalsVisibleTo attribute. It will allow the types from an assembly to be visible from the tests (provided they are in different assemblies).
Otherwise you can leave the property read-only for the external objects but in the same time have a constructor which has an ID parameter and sets the ID property. Then you can call that constructor.
Hope this helps.

Resources