DeleteDatabase is not supported by the provider, Oracle with Entity Framework - oracle

I'm using Model-First approach and Oracle database.
Update2: Fixed Now
On including seed data, I'm getting this error "DeleteDatabase is not supported by the provider"
UPDATE1 If I change seed data type from
public class MySeedData : DropCreateDatabaseAlways<ToolContext> to
public class MySeedData : DropCreateDatabaseIfModelChanges<ToolContext>
this error is replaced by another error:
Exception Model compatibility cannot be checked because the DbContext instance was not created using Code First patterns. DbContext instances created from an ObjectContext or using an EDMX file cannot be checked for compatibility
Seed Data
public class MySeedData : DropCreateDatabaseAlways<ToolContext>
{
protected override void Seed(ToolContext context)
{
base.Seed(context);
var category = new List<CategoryValue>
{
new CategoryValue{Id=1, Name = "Associate"},
new CategoryValue{Id =2, Name = "Professional"},
new CategoryValue{Id=3, Name = "Master"},
new CategoryValue{Id = 4, Name = "Product"},
new CategoryValue{Id = 5, Name = "Portfolio"}
};
category.ForEach(cert => context.CategoryValues.Add(cert));
context.SaveChanges();
}
}
Web.Config
<connectionStrings>
<add name="LMSPriorToolContext"
connectionString="metadata=res://*/Models.LMSPriorToolModel.csdl|res://*/Models.LMSPriorToolModel.ssdl|res://*/Models.LMSPriorToolModel.msl;
provider=Oracle.DataAccess.Client;
provider connection string="DATA SOURCE=DEV;PASSWORD=1234;PERSIST SECURITY INFO=True;USER ID=abc""
providerName="System.Data.EntityClient" />
</connectionStrings>
Application_Start()
Database.SetInitializer<ToolContext>(new SeedData());
Main.cs: EXCEPTION RAISED IN THIS FILE I know when you first try to access database, seed data method or scripts are executed.
using (var dbContext = new ToolContext())
{
var items = dbContext.CategoryValues;
foreach(CategoryValue category in **items**) // **Getting error here**
{
Console.WriteLine(category.Name);
}
}
REFERENCES Seems like I'm missing something here as there is nothing related to Oracle or ODAC
Stack Trace
at System.Data.Common.DbProviderServices.DbDeleteDatabase(DbConnection connection, Nullable`1 commandTimeout, StoreItemCollection storeItemCollection)
at System.Data.Objects.ObjectContext.DeleteDatabase()
at System.Data.Entity.Internal.DatabaseOperations.DeleteIfExists(ObjectContext objectContext)
at System.Data.Entity.Database.Delete()
at System.Data.Entity.DropCreateDatabaseAlways`1.InitializeDatabase(TContext context)
at System.Data.Entity.Database.<>c__DisplayClass2`1.<SetInitializerInternal>b__0(DbContext c)
at System.Data.Entity.Internal.InternalContext.<>c__DisplayClass8.<PerformDatabaseInitialization>b__6()
at System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action)
Please suggest what I'm missing here.

Way of seeding data using DropCreateDatabaseAlways or DropCreateDatabaseIfModelChanges is not supported in Model-First approach.
Change seed data class to:
public class ToolSeedData : IDatabaseInitializer<ToolContext>
{
public void InitializeDatabase(ToolContext context)
{
var category = new List<CategoryValue>
{
new CategoryValue{Id=1, Name = "Associate"},
new CategoryValue{Id =2, Name = "Professional"},
new CategoryValue{Id=3, Name = "Master"},
new CategoryValue{Id = 4, Name = "Product"},
new CategoryValue{Id = 5, Name = "Portfolio"}
};
category.ForEach(cert => context.CategoryValues.Add(cert));
context.SaveChanges();
}
Possible error if you don't use it:
DeleteDatabase is not supported by the provider
Exception Model compatibility cannot be checked because the DbContext instance was not created using Code First patterns.
DbContext instances created from an ObjectContext or using an EDMX
file cannot be checked for compatibility
Microsoft link Seeding database does not work
Hope this helps someone else.

Related

Dynamically Adding Entity Sets to ODataConventionModelBuilder or ODataModelBuilder

Is there a way to dynamically add EntitySets to an ODataConventionModelBuilder.
I'm working on an OData service in .net. Some of the entities we'll be returning are coming from an external assembly. I read the the assembly just fine and get the relevant types but since those types are variables I'm not sure how to define them as entity sets.
Example:
public static void Register(HttpConfiguration config)
{
//some config house keeping here
config.MapODataServiceRoute("odata", null, GetEdmModel(), new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
//more config housekeeping
}
private static IEdmModel GetEdmModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.Namespace = "SomeService";
builder.ContainerName = "DefaultContainer";
//These are the easy, available, in-house types
builder.EntitySet<Dog>("Dogs");
builder.EntitySet<Cat>("Cats");
builder.EntitySet<Horse>("Horses");
// Schema manager gets the rest of the relevant types from reading an assembly. I have them, now I just need to create entity sets for them
foreach (Type t in SchemaManager.GetEntityTypes)
{
builder.AddEntityType(t); //Great! but what if I want EntitySET ?
builder.Function(t.Name).Returns<IQueryable>(); //See if you can put correct IQueryable<Type> here.
//OR
builder.EntitySet<t>(t.Name); //exception due to using variable as type, even though variable IS a type
}
return builder.GetEdmModel();
}
Figured it out. Just add this line inside the loop:
builder.AddEntitySet(t.Name, builder.AddEntityType(t));

Business Process Error: Dynamics CRM and Visual Studio

I have written a C# plugin for post update of the parent record based on the multiple fields.
In this I am trying to calculate the total value in the parent entity based on the values updated in the child entity, which has rate and units fields in it. So basically, total=rate*unit. The code builds fine, but when creating a new form in dynamics crm it genetrates a Business Process Error: Unexpected exception from plug-in (Execute): Parentchild1.parentchildpluginSystem.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
Here is my code:
namespace Parentchild1
{
public class parentchildplugin : IPlugin
{
private Entity abcevent_parent;
public void Execute(IServiceProvider serviceProvider)
{
// Obtain the execution context from the service provider.
IPluginExecutionContext context =
(IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
// Get a reference to the Organization service.
IOrganizationServiceFactory factory =
(IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
if (context.InputParameters != null)
{
//entity = (Entity)context.InputParameters["Target"];
//Instead of getting entity from Target, we use the Image
Entity entity = context.PostEntityImages["PostImage"];
Money rate = (Money)entity.Attributes["abcevent_rate"];
int unit = (int)entity.Attributes["abcevent_unit"];
// EntityReference parent = (EntityReference)entity.Attributes["abcevent_parentid"];
//Multiply
// Money total = new Money(rate.Value * units);
//Set the update entity
Entity parententity = new Entity("abcevent_parent");
//parententity.Id = parent.Id;
//parententity.Attributes["abcevent_total"] = total;
// abcevent_parentid = Guid IOrganizationservice.Create(Entity parentid);
Guid parentGuid = service.Create(abcevent_parent);
EntityReference parent = (EntityReference)entity.Attributes["abcevent_parentid"];
Money total = new Money(rate.Value * unit);
//Update
//service.Update(parententity);
}
the problem you ask for:
The given key was not present in the dictionary.
It is because one key is not in the list, if you try to get an attribute like
int number = (int)entity.Attributes["random_attribute"]
This throws the error, because random_attribute it is not in the context.
You have to make sure the attribute is in the context... the best practice to this is asking for a Contains:
if (entity.Contains("random_attribute"))
This way you know you can safely access to the attribute.
Another reason may be the Image, make sure it is in the context.

NHib 3 Configuration & Mapping returning empty results?

Note: I'm specifically not using Fluent NHibernate but am using 3.x's built-in mapping style. However, I am getting a blank recordset when I think I should be getting records returned.
I'm sure I'm doing something wrong and it's driving me up a wall. :)
Background / Setup
I have an Oracle 11g database for a product by IBM called Maximo
This product has a table called workorder which lists workorders; that table has a field called "wonum" which represents a unique work order number.
I have a "reporting" user which can access the table via the maximo schema
e.g. "select * from maximo.workorder"
I am using Oracle's Managed ODP.NET DLL to accomplish data tasks, and using it for the first time.
Things I've Tried
I created a basic console application to test this
I added the OracleManagedClientDriver.cs from the NHibernate.Driver on the master branch (it is not officially in the release I'm using).
I created a POCO called WorkorderBriefBrief, which only has a WorkorderNumber field.
I created a class map, WorkorderBriefBriefMap, which maps only that value as a read-only value.
I created a console application with console output to attempt to write the lines of work orders.
The session and transaction appear to open correct,
I tested a standard ODP.NET OracleConnection to my connection string
The Code
POCO: WorkorderBriefBrief.cs
namespace PEApps.Model.WorkorderQuery
{
public class WorkorderBriefBrief
{
public virtual string WorkorderNumber { get; set; }
}
}
Mapping: WorkorderBriefBriefMap.cs
using NHibernate.Mapping.ByCode;
using NHibernate.Mapping.ByCode.Conformist;
using PEApps.Model.WorkorderQuery;
namespace ConsoleTests
{
public class WorkorderBriefBriefMap : ClassMapping<WorkorderBriefBrief>
{
public WorkorderBriefBriefMap()
{
Schema("MAXIMO");
Table("WORKORDER");
Property(x=>x.WorkorderNumber, m =>
{
m.Access(Accessor.ReadOnly);
m.Column("WONUM");
});
}
}
}
Putting it Together: Program.cs
namespace ConsoleTests
{
class Program
{
static void Main(string[] args)
{
NHibernateProfiler.Initialize();
try
{
var cfg = new Configuration();
cfg
.DataBaseIntegration(db =>
{
db.ConnectionString = "[Redacted]";
db.Dialect<Oracle10gDialect>();
db.Driver<OracleManagedDataClientDriver>();
db.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
db.BatchSize = 500;
db.LogSqlInConsole = true;
})
.AddAssembly(typeof(WorkorderBriefBriefMap).Assembly)
.SessionFactory().GenerateStatistics();
var factory = cfg.BuildSessionFactory();
List<WorkorderBriefBrief> query;
using (var session = factory.OpenSession())
{
Console.WriteLine("session opened");
Console.ReadLine();
using (var transaction = session.BeginTransaction())
{
Console.WriteLine("transaction opened");
Console.ReadLine();
query =
(from workorderbriefbrief in session.Query<WorkorderBriefBrief>() select workorderbriefbrief)
.ToList();
transaction.Commit();
Console.WriteLine("Transaction Committed");
}
}
Console.WriteLine("result length is {0}", query.Count);
Console.WriteLine("about to write WOs");
foreach (WorkorderBriefBrief wo in query)
{
Console.WriteLine("{0}", wo.WorkorderNumber);
}
Console.WriteLine("DONE!");
Console.ReadLine();
// Test a standard connection below
string constr = "[Redacted]";
OracleConnection con = new OracleConnection(constr);
con.Open();
Console.WriteLine("Connected to Oracle Database {0}, {1}", con.ServerVersion, con.DatabaseName.ToString());
con.Dispose();
Console.WriteLine("Press RETURN to exit.");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("Error : {0}", ex);
Console.ReadLine();
}
}
}
}
Thanks in advance for any help you can give!
Update
The following code (standard ADO.NET with OracleDataReader) works fine, returning the 16 workorder numbers that it should. To me, this points to my use of NHibernate more than the Oracle Managed ODP.NET. So I'm hoping it's just something stupid that I did above in the mapping or configuration.
// Test a standard connection below
string constr = "[Redacted]";
OracleConnection con = new Oracle.ManagedDataAccess.Client.OracleConnection(constr);
con.Open();
Console.WriteLine("Connected to Oracle Database {0}, {1}", con.ServerVersion, con.DatabaseName);
var cmd = new OracleCommand();
cmd.Connection = con;
cmd.CommandText = "select wonum from maximo.workorder where upper(reportedby) = 'MAXADMIN'";
cmd.CommandType = CommandType.Text;
Oracle.ManagedDataAccess.Client.OracleDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader.GetString(0));
}
con.Dispose();
When configuring NHibernate, you need to tell it about your mappings.
I found the answer -- thanks to Oskar's initial suggestion, I realized it wasn't just that I hadn't added the assembly, I also needed to create a new mapper.
to do this, I added the following code to the configuration before building my session factory:
var mapper = new ModelMapper();
//define mappingType(s) -- could be an array; in my case it was just 1
var mappingType = typeof (WorkorderBriefBriefMap);
//use AddMappings instead if you're mapping an array
mapper.AddMapping(mappingType);
//add the compiled results of the mapper to the configuration
cfg.AddMapping(mapper.CompileMappingForAllExplicitlyAddedEntities());
var factory = cfg.BuildSessionFactory();

Mstest Controller and Service Layer With Dependency Injection (Autofac) and Automapper

I'm trying to bring test layer to my project but I'm not getting there :( hope someone can help me.
Controller (based on Automapper mapping and Dependency Injection Container):
public virtual ActionResult SearchCategories(string keywords)
{
var result = _categoryService.SearchCategories(keywords);
var resultViewModel = Mapper.
Map<IList<SearchCategoriesDto>,
IList<SearchCategoriesViewModel>>(result);
return View(resultViewModel);
}
Service Layer:
public IList<SearchCategoriesDto> SearchCategories(String keywords)
{
// Find the keywords in the Keywords table
var keywordQuery = _keywordRepository.Query;
foreach (string keyword in splitKeywords)
{
keywordQuery = keywordQuery.Where(p => p.Name == keyword);
}
// Get the Categories from the Search
var keywordAdCategoryQuery = _keywordAdCategoryRepository.Query;
var categoryQuery = _categoryRepository.Query;
var query = from k in keywordQuery
join kac in keywordAdCategoryQuery on k.Id equals kac.Keyword_Id
join c in categoryQuery on kac.Category_Id equals c.Id
select new SearchCategoriesDto
{
Id = c.Id,
Name = c.Name,
SearchCount = keywordAdCategoryQuery
.Where(s => s.Category_Id == c.Id)
.GroupBy(p => p.Ad_Id).Count(),
ListController = c.ListController,
ListAction = c.ListAction
};
var searchResults = query.Distinct().ToList();
return searchResults;
}
Test maded but not working:
[TestMethod]
public void Home_SearchCategories_Test()
{
// Setup
var catetoryService = new CategoryService(
_categoryRepository,
_keywordRepository,
_keywordAdCategoryRepository);
// Act
var result = catetoryService.SearchCategories("audi");
// Add verifications here
Assert.IsTrue(result.Count > 0);
}
Thanks.
I am assuming you want to create an integration test for your category service, using real repositories and database. (as oposed to an unit test where you would use stub\mocks for those repositories and test the service class in isolation)
So you would have a seaparated test assembly where you will add your integration tests, for example having a class for the integration tests at the service level.
On that class you will then create instances of all the repositories and the CategoryService before running each test, on a method with the attribute [TestInitialize]. (A method with this attribute will be run by msTest before each test)
As you are also truly working with the database you would like to be sure that any resources used are disposed. For example, disposing an entity framework context. In that case you would add a method with an attribute [TestCleanup] where you will perform any cleanup logic needed. (A method with this attribute will be run by msTest after each test)
With those methods you will make sure you have a fresh service and repositories instances on each test. Then you will implement each individual integration test following the AAA pattern (Arrange, Act, Assert)
So an example of your integration test class with that single test may look like:
public class CategoryServiceIntegrationTest
{
//dependencies of your class under test
private ICategoryRepository _categoryRepository;
private IKeywordRepository _keywordRepository;
private IKeywordAdCategoryRepository _keywordAdCategoryRepository;
//your class under test
private CategoryService _categoryService;
[TestInitialize]
public void InitializeBeforeRunningATest()
{
//manually create instances of the classes implementing the repositories
//I donĀ“t know about how they are implemented but I guess
//you would need to provide the name of a connection string in the config file (in that case this should be in a config file of the test project)
//,the connection string itself
//or maybe you need to initialize an entity framework context
_categoryRepository = new CategoryRepository( /*whatever you need to provide*/);
_keywordRepository = new KeywordRepository( /*whatever you need to provide*/);
_keywordAdCategoryRepository = new KeywordAdCategoryRepository( /*whatever you need to provide*/);
//Create the class under test with all repositories dependencies
//as it is an integration test, they are your real objects and not mocks\stubs
_categoryService = new CategoryService(_categoryRepository,
_keywordRepository,
_keywordAdCategoryRepository);
}
[TestCleanup]
public void CleanDatabaseResources()
{
//just in case you need to do something like disposing an EF context object
}
[TestMethod]
public void Home_SearchCategories_Test()
{
// Arrange
var keywords = "audi";
// Act (the _categoryService instance was created in the initialize method)
var result = _categoryService.SearchCategories(keywords);
// Assert
Assert.IsTrue(result.Count > 0);
}
}
Solution to build an Integration test for a Service (in this case, Category Service), using Autofac, Automapper (not necessary in this Service but if it would be necessary, you would need to put in the TestInitialize method as you can see in the coment line in the following solution) and Entity Framework with Daniel J.G. help (thanks Daniel):
First of all I created a separated Test Project using MSTest (only because there is a lot of documentation about it).
Second you need to put the connection string for the Entity Framework where the test data is:
<connectionStrings>
<add name="DB" connectionString="Data Source=.\sqlexpress;Database=DBNAME;UID=DBUSER;pwd=DBPASSWORD;MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" />
</connectionStrings>
In the < configuration > section after the < / configSections >
Third you create the class for the test:
namespace Heelp.Tests
{
[TestClass]
public class CategoryServiceIntegrationTest
{
// Respositories dependencies
private IRepository<Category> _categoryRepository;
private IRepository<Keyword> _keywordRepository;
private IRepository<KeywordAdCategory> _keywordAdCategoryRepository;
// Service under test: Category Service
private CategoryService _categoryService;
// Context under test: HeelpDB Connection String in app.config
private HeelpDbContext db;
[TestInitialize]
public void InitializeBeforeRunningATest()
{
// IoC dependencies registrations
AutofacConfig.RegisterDependencies();
// HERE YOU CAN CALL THE AUTOMAPPER CONFIGURE METHOD
// IN MY PROJECT I USE AutoMapperConfiguration.Configure();
// IT'S LOCATED IN THE App_Start FOLDER IN THE AutoMapperConfig.cs CLASS
// CALLED FROM GLOBAL.ASAX Application_Start() METHOD
// Database context initialization
db = new HeelpDbContext();
// Repositories initialization
_categoryRepository = new Repository<Category>(db);
_keywordRepository = new Repository<Keyword>(db);
_keywordAdCategoryRepository = new Repository<KeywordAdCategory>(db);
// Service initialization
_categoryService = new CategoryService(_categoryRepository,
_keywordRepository,
_keywordAdCategoryRepository);
}
[TestCleanup]
public void CleanDatabaseResources()
{
// Release the Entity Framework Context for other tests that will create a fresh new context.
// With this method, we will make sure that we have a fresh service and repositories instances on each test.
db.Dispose();
}
[TestMethod]
public void Home_SearchCategories_Test()
{
// Arrange
var keywords = "audi";
// Act (the _categoryService instance was created in the initialize method)
var result = _categoryService.SearchCategories(keywords);
// Assert
Assert.IsTrue(result.Count > 0);
}
}
}
Now you just have to run the test to see if it passes.
To garantee integration tests, I would recomend a second database identical from the original/production database in terms of tables, but with only your test data.
This will ensure that the tests results will remain the same based on your test data.
The only drawback is that you will need to keep sincronized the tables, but you can use SQL Admin Studio Freeware Tool from Simego to achieve that.
Regards.

PrepareResponse().AsActionResult() throws unsupported exception DotNetOpenAuth CTP

Currently I'm developing an OAuth2 authorization server using DotNetOpenAuth CTP version. My authorization server is in asp.net MVC3, and it's based on the sample provided by the library. Everything works fine until the app reaches the point where the user authorizes the consumer client.
There's an action inside my OAuth controller which takes care of the authorization process, and is very similar to the equivalent action in the sample:
[Authorize, HttpPost, ValidateAntiForgeryToken]
public ActionResult AuthorizeResponse(bool isApproved)
{
var pendingRequest = this.authorizationServer.ReadAuthorizationRequest();
if (pendingRequest == null)
{
throw new HttpException((int)HttpStatusCode.BadRequest, "Missing authorization request.");
}
IDirectedProtocolMessage response;
if (isApproved)
{
var client = MvcApplication.DataContext.Clients.First(c => c.ClientIdentifier == pendingRequest.ClientIdentifier);
client.ClientAuthorizations.Add(
new ClientAuthorization
{
Scope = OAuthUtilities.JoinScopes(pendingRequest.Scope),
User = MvcApplication.LoggedInUser,
CreatedOn = DateTime.UtcNow,
});
MvcApplication.DataContext.SaveChanges();
response = this.authorizationServer.PrepareApproveAuthorizationRequest(pendingRequest, User.Identity.Name);
}
else
{
response = this.authorizationServer.PrepareRejectAuthorizationRequest(pendingRequest);
}
return this.authorizationServer.Channel.PrepareResponse(response).AsActionResult();
}
Everytime the program reaches this line:
this.authorizationServer.Channel.PrepareResponse(response).AsActionResult();
The system throws an exception which I have researched with no success. The exception is the following:
Only parameterless constructors and initializers are supported in LINQ to Entities.
The stack trace: http://pastebin.com/TibCax2t
The only thing I've done differently from the sample is that I used entity framework's code first approach, an I think the sample was done using a designer which autogenerated the entities.
Thank you in advance.
If you started from the example, the problem Andrew is talking about stays in DatabaseKeyNonceStore.cs. The exception is raised by one on these two methods:
public CryptoKey GetKey(string bucket, string handle) {
// It is critical that this lookup be case-sensitive, which can only be configured at the database.
var matches = from key in MvcApplication.DataContext.SymmetricCryptoKeys
where key.Bucket == bucket && key.Handle == handle
select new CryptoKey(key.Secret, key.ExpiresUtc.AsUtc());
return matches.FirstOrDefault();
}
public IEnumerable<KeyValuePair<string, CryptoKey>> GetKeys(string bucket) {
return from key in MvcApplication.DataContext.SymmetricCryptoKeys
where key.Bucket == bucket
orderby key.ExpiresUtc descending
select new KeyValuePair<string, CryptoKey>(key.Handle, new CryptoKey(key.Secret, key.ExpiresUtc.AsUtc()));
}
I've resolved moving initializations outside of the query:
public CryptoKey GetKey(string bucket, string handle) {
// It is critical that this lookup be case-sensitive, which can only be configured at the database.
var matches = from key in db.SymmetricCryptoKeys
where key.Bucket == bucket && key.Handle == handle
select key;
var match = matches.FirstOrDefault();
CryptoKey ck = new CryptoKey(match.Secret, match.ExpiresUtc.AsUtc());
return ck;
}
public IEnumerable<KeyValuePair<string, CryptoKey>> GetKeys(string bucket) {
var matches = from key in db.SymmetricCryptoKeys
where key.Bucket == bucket
orderby key.ExpiresUtc descending
select key;
List<KeyValuePair<string, CryptoKey>> en = new List<KeyValuePair<string, CryptoKey>>();
foreach (var key in matches)
en.Add(new KeyValuePair<string, CryptoKey>(key.Handle, new CryptoKey(key.Secret, key.ExpiresUtc.AsUtc())));
return en.AsEnumerable<KeyValuePair<string,CryptoKey>>();
}
I'm not sure that this is the best way, but it works!
It looks like your ICryptoKeyStore implementation may be attempting to store CryptoKey directly, but it's not a class that is compatible with the Entity framework (due to not have a public default constructor). Instead, define your own entity class for storing the data in CryptoKey and your ICryptoKeyStore is responsible to transition between the two data types for persistence and retrieval.

Resources