Data driven unit test breaking entity framework connection - entity-framework

I have an application that uses entity framework. I am writing a unit test in which I would like to use data driven testing from a CSV file.
However, when I run the test, I get an error that the sqlserver provider cannot be loaded:
Initialization method UnitTest.CalculationTest.MyTestInitialize threw
exception. System.InvalidOperationException:
System.InvalidOperationException: The Entity Framework provider type
'System.Data.Entity.SqlServer.SqlProviderServices,
EntityFramework.SqlServer' registered in the application config file
for the ADO.NET provider with invariant name 'System.Data.SqlClient'
could not be loaded. Make sure that the assembly-qualified name is
used and that the assembly is available to the running application.
If I remove the data driven aspects and just test a single value, then the test works.
If I just use the data driven aspects and remove the Entity Framework stuff, then the test works.
So, its only when I try to use data driven test with entity framework active at the same time do I get the error. So, where am I going wrong here?
Here's my test method:
[TestMethod, TestCategory("Calculations")
, DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV"
, "ConvertedMeanProfileDepth.csv", "ConvertedMeanProfileDepth#csv"
, Microsoft.VisualStudio.TestTools.UnitTesting.DataAccessMethod.Sequential)
, DeploymentItem("ConvertedMeanProfileDepth.csv")]
public void ConvertedMeanProfileDepthTest()
{
ConvertedMeanProfileDepth target = new ConvertedMeanProfileDepth();
Decimal mpd = decimal.Parse(this.TestContext.DataRow["mpd"].ToString());
Decimal expected = decimal.Parse(this.TestContext.DataRow["converted"].ToString());
Decimal actual;
actual = target.Calculate(mpd);
Assert.AreEqual(expected, actual);
}

So I managed to work it out in the end. For future reference, here's the solution:
Rob Lang's post, Entity Framework upgrade to 6 configuration and nuget magic, reminded me of the issue here:
When a type cannot be loaded for a DLL that is referenced in a
project, it usually means that it has not been copied to the output
bin/ directory. When you're not using a type from a referenced
library, it will not be copied.
And this will raise its ugly head the moment you use deployment items in your tests. If you use a deployment item in your test, then all of the required binaries are copied to the deployment directory. Problem is, if you are using dynamically loaded items, then the test suite does not know it has to copy those items.
With Entity Framework, this means that your providers will not be copied to the deployment location and you will receive the error as per my question.
To resolve the issue, simply ensure that your entity framework provider is also marked as a deployment item.
So, note the inclusion of DeploymentItem(#"EntityFramework.SqlServer.dll") in my test attributes. All works perfectly from here:
[TestMethod, TestCategory("Calculations")
, DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV"
, "ConvertedMeanProfileDepth.csv", "ConvertedMeanProfileDepth#csv"
, Microsoft.VisualStudio.TestTools.UnitTesting.DataAccessMethod.Sequential)
, DeploymentItem("ConvertedMeanProfileDepth.csv")
, DeploymentItem(#"EntityFramework.SqlServer.dll")]
public void ConvertedMeanProfileDepthTest()
{
ConvertedMeanProfileDepth target = new ConvertedMeanProfileDepth();
Decimal mpd = decimal.Parse(this.TestContext.DataRow["mpd"].ToString());
Decimal expected = decimal.Parse(this.TestContext.DataRow["converted"].ToString());
Decimal actual;
actual = target.Calculate(mpd);
Assert.AreEqual(expected, actual);
}

Related

Breeze: cannot execute _executeQueryCore until metadataStore is populated

I was using Breeze v1.1.2 that came with the Hot Towel template which has now been extended to form my project. I made the mistake of updating the NuGet package to the current 1.3.3 (I never learn). Anyway, all was well, and now not so much!
I followed the instructions in the release notes and other docs to change my BreezeWebApiConfig file to:
[assembly: WebActivator.PreApplicationStartMethod(
typeof(BreezeWebApiConfig), "RegisterBreezePreStart")]
namespace MyApp.App_Start {
public static class BreezeWebApiConfig {
public static void RegisterBreezePreStart() {
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "BreezeApi",
routeTemplate: "breeze/{controller}/{action}"
);}}}
And the config.js file (which provides the serviceName to the EntityManager constructor) to:
var remoteServiceName = 'breeze/breeze'; // NEW version
//var remoteServiceName = 'api/breeze'; // OLD version
And my BreezeController if you're interested:
[BreezeController]
public class BreezeController : ApiController
{
readonly EFContextProvider<MyDbContext> _contextProvider =
new EFContextProvider<MyDbContext>();
[HttpGet]
public string Metadata()
{
return _contextProvider.Metadata();
}
[HttpGet]
public IQueryable<SomeItem> SomeItems()
{
// Do stuff here...
}
}
Now I get the "cannot execute _executeQueryCore until metadataStore is populated" error.
What am I missing here?
EDIT:
I perhaps left out the part you needed... Above in the SomeItems() method, the stuff that actually gets done is a call to the GetMeSomeData() method in the MyDBContext class. This method makes the following call to a stored procedure to get the data.
public virtual ObjectResult<SomeItem> GetMeSomeData(string inParam)
{
var p = new object[] { new SqlParameter("#inParam", inParam) };
var retVal = ((IObjectContextAdapter)this).ObjectContext.ExecuteStoreQuery<SomeItem>("exec GetData #SN", p);
return retVal;
}
Now given my limited understanding, the call to Metadata() is not failing, but I don't think it has any idea what the entity model is when coming back, even though somewhere along the line, it should figure that out from the entity model I do have (i.e. SomeItem)? The return string from Metadata() doesn't have any information about the entity. Is there a way to make it aware? Or am I just completely off in left field playing with the daisies?
Hard to say based on this report. Let's see if Breeze is right.
Open the browser debugging tools and look at the network traffic. Do you see an attempt to get metadata from the server before you get that error? If so, did it succeed? Or 404? Or 500? What was the error?
I'm betting it didn't even try. If it didn't, the usual reason is that you tried some Breeze operation before your first query ... and you didn't ask for metadata explicitly either. Did you try to create an entity? That requires metadata.
The point is, you've got to track down the Breeze operation that precipitates the error. Sure everything should just work. The world should be rainbows and unicorns. When it isn't, we heave a sigh, break out the debugger, and start with the information that the error gave us.
And for the rest of you out there ... upgrading to a new Breeze version is a good thing.
Happy coding everyone.
Follow-up to your update
Breeze doesn't know how you get your data on the back-end. If the query result has a recognizable entity in it, Breeze will cache that. It's still up to you in the query callback to ensure that what you deliver to the caller is something meaningful.
You say that you're server-side metadata method doesn't have any idea what SomeItem is? Then it's not much use to the client. If it returns a null string, Breeze may treat that as "no metadata at all" in which case you should be getting the "cannot execute _executeQueryCore until metadataStore is populated" error message. Btw, did you check the network traffic to determine what your server actually returned in response to the metadata request (or if there was such a request)?
There are many ways to create Metadata on the server. The easiest is to use EF ... at least as a modeling tool at design time. What's in that MyDbContext of yours? Why isn't SomeItem in there?
You also can create metadata on the client if you don't want to generate it from the server. You do have to tell the Breeze client that you've made that choice. Much of this is explained in the documentation "Metadata Format".
I get the feeling that you're kind of winging it. You want to stray from the happy path ... and that's cool. But most of us need to learn to walk before we run.

Entity Framework ConnectionString Parsing Exception

I can't find how my connectionString syntax is wrong. Can anyone suggest a way to figure this out? I am having a difficulty using EF with my connection string. I am new to EF.
I am using Sybase Anywhere 12 database.
I'm using the Table-First ObjectContext with EDMX in a separate class library refenced by a web application.
I'm using a Ninject Module in my class library to bind my repositories.
I'm using a ODBC DataStore called "Test"
Other information EF 4.3.1.0, .NET 4, VS2010
My main web application web.config has the EF connection string copied to it as:
<connectionStrings>
<add name="Entities"connectionString="metadata=res://*/MyEntities.csdl|res://*/MyEntities.ssdl|res://*/MyEntities.msl;provider=iAnywhere.Data.SQLAnywhere;provider connection string="UserID=aUser;Password=aPassword;DataSourceName=Test"" providerName="iAnywhere.Data.SQLAnywhere"/>
</connectionStrings>
When I initialize my Entity/ObjectContext in my Repository (see using statement below) it returns an error: "The specified named connection is either not found in the configuration, not intended to be used with the EntityClient provider, or not valid."
using (var context = new Entities())
{
return {Linq to Entity here}
}
I turned on CLR exceptions on the debugger and found the code throws the error in the .NET Framework here:
EntityConnection.cs
effectiveConnectionOptions = new DbConnectionOptions(setting.ConnectionString, EntityConnectionStringBuilder.Synonyms, false);
edmx designer generated:
/// <summary>
/// Initializes a new Entities object using the connection string found in the 'Entities' section of the application configuration file.
/// </summary>
public Entities() : base("name=Entities", "Entities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
I can see my connection string there, so it is having a difficult time parsing the connectionString. I have tried many different permutations of syntax and haven't found anything it accepts including:
Explicitly naming the assembly for entity files instead of a wildcard(e.g. metadata=res://MyDomain/MyEntities.csdl...)
Using Sybase friendly ODBC attributes such as UID instead of UserID, PWD instead of Password, and DBN instead of DataSourceName.
Thanks.
I got everything working and the only reason I can think of is that I deleted my ASP .NET 4.0 temp files. Also, I must add I changed my process from using an integration test to test this piece to using a unit test. I did not do unit tests first, because our build server does not have a database on it.
Once I was able to prove that it was working there, I decided to delete my temp files. After that, everything started working properly. So, some sort of cache issue was occurring in my application. I used the same connectionString that I mentioned above.
Actually, I used the domain name of the Metadata "metadata=res://MyDomain/MyEntitities.csdl" rather than */MyEntities.csdl. I don't plan on changing the domain any time soon. In fact, that is just what may have caused some of the issue, because I had changed the location, name, and namespace of MyEntities.Domain where the EF was.

Entity Framework issue when creating unit tests

I am specifically getting the following error:
"The specified named connection is either not found in the configuration, not intended to be used with the EntityClient provider, or not valid."
[TestMethod()]
public void salesOrderFillListTest()
{
SalesOrderController_Accessor target = new SalesOrderController_Accessor();
string orderNumber = "1954120";
SalesOrderData result;
result = target.FillingOrder(orderNumber);
Assert.AreEqual(null, result.ErrorMessage);
Assert.AreEqual(32, result.LineItems.Count);
Assert.AreEqual("WRA-24-NFL-CLEV", result.LineItems[7].ItemNumber);
Assert.AreEqual(2, result.LineItems[7].OrderQuantity);
Assert.AreEqual(1, result.LineItems[7].FillingFilledQty);
Assert.AreEqual(1, result.LineItems[7].FillingRemainQty);
}
The error is coming up on the line:
result = target.FillingOrder(orderNumber);
I'm a junior developer and haven't had much experience with the many possible causes for this error. My App.config page contains the appropriate connection strings. Any ideas where to look for this one?
Thanks!
I was able to successfully run tests found in another test project in the same solution. After looking more carefully I found that there were a few differences between the two connection strings in each project. The data in the failing test project had become antiquated. I updated the connection string and error resolved.
Thanks.

Entity Framework RIA Services How do I include entities within an included entity

I have the following hierarchy:
AccountCatagory
AccountType
AccoungGroup
GeneralLedger
SubsidiaryLedger
so each AccountCatagory has AccountTypes, each AccountType has AccountGroups...
Which needs to be loaded in to a tree view:
I need to load everything when the account category is loaded and I wrote it like this:
public IQueryable<AccountCatagory> GetAccountCatagories()
{
return this.ObjectContext.AccountCatagories.Include("AccountTypes");
}
Which works fine but only loads AccountTypes. within each AccountCatagory.
Writing an Include on each of the entities GetQuery doesn’t work.
How do I tell RIA services to Include entity when the Included entity also has an include/entity to load?
Here is an example of the way I got mine to work, assuming that all of your foreign keys are set up properly and the proper changes have been made in the metadata file of your Domain Service:
return ObjectContext.Users.Include("AccessRole")
.Include("AccessRole.AccessRoleReports")
I have never tried including objects with so many subtypes, but I assume this may work:
return this.ObjectContext.AccountCatagories.Include("AccountTypes")
.Include("AccountTypes.AccountGroups")
.Include("AccountTypes.AccountGroups.GeneralLedger")
.Include("AccountTypes.AccountGroups.GeneralLedger.SubsidiaryLedger");

EF 4 Self Tracking Entities does not work as expected

I am using EF4 Self Tracking Entities (VS2010 Beta 2 CTP 2 plus new T4 generator). But when I try to update entity information it does not update to database as expected.
I setup 2 service calls. one for GetResource(int id) which return a resource object. the second call is SaveResource(Resource res); here is the code.
public Resource GetResource(int id)
{
using (var dc = new MyEntities())
{
return dc.Resources.Where(d => d.ResourceId == id).SingleOrDefault();
}
}
public void SaveResource(Resource res)
{
using (var dc = new MyEntities())
{
dc.Resources.ApplyChanges(res);
dc.SaveChanges();
// Nothing save to database.
}
}
//Windows Console Client Calls
var res = service.GetResource(1);
res.Description = "New Change"; // Not updating...
service.SaveResource(res);
// does not change anything.
It seems to me that ChangeTracker.State is always show as "Unchanged".
anything wrong in this code?
This is probably a long shot... but:
I assume your Service is actually in another Tier? If you are testing in the same tier you will have problems.
Self Tracking Entities (STEs) don't record changes until when they are connected to an ObjectContext, the idea is that if they are connected to a ObjectContext it can record changes for them and there is no point doing the same work twice.
STEs start tracking once they are deserialized on the client using WCF, i.e. once they are materialized to a tier without an ObjectContext.
If you look through the generated code you should be able to see how to turn tracking on manually too.
Hope this helps
Alex
You have to share assembly with STEs between client and service - that is the main point. Then when adding service reference make sure that "Reuse types in referenced assemblies" is checked.
The reason for this is that STEs contain logic which cannot be transfered by "Add service reference", so you have to share these types to have tracing logic on client as well.
After reading the following tip from Daniel Simmons, the STE starts tracking. Here is the link for the full article. http://msdn.microsoft.com/en-us/magazine/ee335715.aspx
Make certain to reuse the Self-Tracking Entity template’s generated entity code on your client. If you use proxy code generated by Add Service Reference in Visual Studio or some other tool, things look right for the most part, but you will discover that the entities don’t actually keep track of their changes on the client.
so in the client make sure you don't use add service reference to get the proxy instead access service through following code.
var svc = new ChannelFactory<IMyService>("BasicHttpBinding_IMyService").CreateChannel();
var res = svc.GetResource(1);
If you are using STEs without WCF you may have to call StartTracking() manually.
I had the same exact problem and found the solution.
It appears that for the self-tracking entities to automatically start tracking, you need to reference your STE project before adding the service reference.
This way Visual Studio generates some .datasource files which does the final trick.
I found the solution here:
http://blogs.u2u.be/diederik/post/2010/05/18/Self-Tracking-Entities-with-Validation-and-Tracking-State-Change-Notification.aspx
As for starting the tracking manually, it seems that you do not have these methods on the client-side.
Hope it helps...