entity Framework Seeding related data - entity-framework

I'm trying to figure out how to seed one to many data elements in the seed method of Entity Framework.
context.AddressTypes.AddOrUpdate(
p => p.Name,
new AddressType { Name = "Original" },
new AddressType { Name = "Shipping" },
new AddressType { Name = "Billing" }
);
context.Addresses.AddOrUpdate(
a => a.Address1,
new Address { Address1 = "123 West Main",
City = "Hannibal",
Region = "MO",
PostalCode = "12345",
Country = "USA",
Type = new AddressType { Id=1 } }
);
How do I add one of the three address types to the address object I am seeding? If I do it the way I have shown it creates a new object in the AddressTypes table.

Related

Dynamic list using array from anthor list

My application is ASP.NET MVC 5 / SQL Server.
I am trying to select specific columns from a list based on an array:
First list has 200 columns: Age, Gender, .....
var list1 = _reportRepository.ShowMasteView().ToList();
Second list has 20 columns: Age, Gender, ......
From the view I select the items to be displayed:
string[] lits2 = showColumn.Where(c => c.Value == true).Select(c=> c.Key).ToArray();
I get
To get these two specific columns, I tried
var nList = list1.Select(t2 => lits2.Any(t1 => t2.Contains(t1)));
I get an error
Can not resolve symbol "Contains"
I was able to do it using the following
var keys = "Age,Gender";
var connection =
ConfigurationManager.ConnectionStrings["DALEntities"].ConnectionString;
using (var dataAdapter = new SqlDataAdapter("SELECT " + keys
+ " from dbo.vw_MasterView", connection))
{
var dataTable = new DataTable();
dataAdapter.Fill(dataTable);
dataAdapter.FillSchema(dataTable, SchemaType.Mapped);
return dataTable;
}
Is there a better way in linq?
From my understand it appears you are trying to extract/select a dynamic object that only has the desired properties/columns.
This can be achieved by building a dynamic expression/function to apply to the Select
The following builds an expression based on the model type and the provided properties
static class DynamicExtensions {
public static IQueryable<dynamic> SelectDynamic<TModel>(this IQueryable<TModel> query, ISet<string> propertyNames) {
var selector = query.BuildSelectorFor(propertyNames);
return query.Select(selector);
}
static Expression<Func<TModel, dynamic>> BuildSelectorFor<TModel>(this IQueryable<TModel> query, ISet<string> propertyNames) {
var modelType = typeof(TModel);
var properties = modelType.GetProperties().Where(p => propertyNames.Contains(p.Name));
// Manually build the expression tree for
// the lambda expression v => new { PropertyName = v.PropertyName, ... }
// (TModel v) =>
var parameter = Expression.Parameter(modelType, "v");
// v.PropertyName
var members = properties.Select(p => Expression.PropertyOrField(parameter, p.Name));
var addMethod = typeof(IDictionary<string, object>).GetMethod(
"Add", new Type[] { typeof(string), typeof(object) });
// { { "PropertyName", v.PropertyName}, ... }
var elementInits = members.Select(m =>
Expression.ElementInit(addMethod, Expression.Constant(m.Member.Name), Expression.Convert(m, typeof(object))));
// new ExpandoObject()
var newExpando = Expression.New(typeof(ExpandoObject));
// new ExpandoObject() { { "PropertyName", v.PropertyName}, ... }
var expando = Expression.ListInit(newExpando, elementInits);
// (TModel v) => new ExpandoObject() { { "PropertyName", v.PropertyName}, ... }
var lambdaExpression = Expression.Lambda<Func<TModel, dynamic>>(expando, parameter);
return lambdaExpression;
}
}
This takes advantage of ExpandoObject whose members can be dynamically added and removed at run time.
The following test was used as an example of how the above function is invoked.
[TestMethod]
public void DynamicList() {
var list1 = new List<Person>
{
new Person{ Gender = "Male", Age = 10, FirstName = "Nama1", SampleNumber = 12},
new Person{ Gender = "Male", Age = 12, FirstName = "Nama2", SampleNumber = 13},
new Person{ Gender = "Female", Age = 13, FirstName = "Nama3", SampleNumber = 14},
new Person{ Gender = "Male", Age = 14, FirstName = "Nama4", SampleNumber = 15},
};
var keys = new string[] { "Age", "Gender", };
var nList = list1.AsQueryable().SelectDynamic(new HashSet<string>(keys));
foreach (IDictionary<string, object> row in nList) {
var msg = $"{{ {keys[0]} = {row[keys[0]]}, {keys[1]} = {row[keys[1]]} }}";
Debug.WriteLine(msg);
}
}
and produces the following output
{ Age = 10, Gender = Male }
{ Age = 12, Gender = Male }
{ Age = 13, Gender = Female }
{ Age = 14, Gender = Male }
The dynamic objects can be used in the View and it is a simple matter of calling the desired members.
For example suppose you have a model as follows
public class MyViewModel {
public string MyProperty { get; set; }
public string[] Keys { get; set; }
public List<dynamic> MyDynamicProperty { get; set; }
}
that was populated with data and given to the view
var list1 = _reportRepository.ShowMasteView();
var keys = new string[] { "Age", "Gender", };
var nList = list1.AsQueryable().SelectDynamic(new HashSet<string>(keys));
var viewModel = new MyViewModel {
MyProperty = "Hello World",
MyDynamicProperty = nList.ToList(),
Keys = keys
};
return View(viewModel);
Then in the view you can use the model as desired, casting to get access to members in the expando object.
#model MyViewModel
...
<h2>#Model.MyProperty</h2>
<table>
<tr>
#foreach(string key in Model.Keys) {
<th>#key</th>
}
</tr>
#foreach (IDictionary<string, object> row in Model.MyDynamicProperty) {
<tr>
#foreach(string key in Model.Keys) {
<td>#row[#key]</td>
}
</tr>
}
</table>
I think you just need to use Contains on your list2.
var nList = list1.Where(t => lits2.Contains(t1));
Contains is a method for Lists. The code you had was trying to use it on a string.
If you have two list of a person's class
public class Person
{
public int id { get; set; }
public string name { get; set; }
}
If the lists are as below:
var list1 = new List<Person>
{
new Person{ id = 1, name = "Nama1"},
new Person{ id = 2, name = "Nama2"},
new Person{ id = 3, name = "Nama3"},
new Person{ id = 4, name = "Nama4"},
};
var list2 = new List<Person>
{
new Person{ id = 1, name = "Nama1"},
new Person{ id = 2, name = "Nama2"},
};
You can filter in the following ways
var keys = list2.Select(x => x.id).ToList();
var filter1= list1.Where(x => keys.Contains(x.id)).ToList();
var filter2= list1.Where(x => keys.Contains(x.id)).Select(x => new { x.name }).ToList();
var filter3= list1.Select(x => new
{
id = x.id,
name = x.name,
check = keys.Contains(x.id)
}).Where(x => x.check).ToList();
If you have array of string
you can use below code
array string same
var lis1 = new string[] {"name1", "name2","name3" };
var lis2 = new string[] { "name1" };
You can filter array of string in the following ways
var items1= lis1.Where(x=>lis2.Contains(x)).ToList();
var items= lis1.Select(x=> new { x, check= lis2.Contains(x) }).Where(x=>x.check == true).ToList();

What steps to get rid of Collection was modified; enumeration operation may not execute. Error?

Our programming involves some Mock testing using In-Memory Data. Therefore, we implemented the following code that would first create In-Memory Data of Customer objects
// Let us create some in-memory data
// Create a list of Customer
List<Customer> listOfCustomers = new List<BlahBlahExample.Domain.Objects.Customer>()
{ new Customer { CustomerID = "1 ",Orders = new HashSet<Order>(), CustomerDemographics = new HashSet<CustomerDemographic>(), CompanyName = "Chicago Bulls", ContactName = "Michael Jordan", ContactTitle = "top basket ball player", Address = "332 testing lane", City = "Chicago", Region = "Illinois", PostalCode = "484894", Country = "USA", Phone = "3293993", Fax = "39393" },
new Customer { CustomerID = "2 ",Orders = new HashSet<Order>(),CustomerDemographics = new HashSet<CustomerDemographic>() , CompanyName = "Miami Heat", ContactName = "Lebron James", ContactTitle = "second best basket ball player", Address = "90 test street", City = "Miami", Region = "Florida", PostalCode = "4869394", Country = "USA", Phone = "3293213", Fax = "33393" },
new Customer { CustomerID = "3 ",Orders = new HashSet<Order>(),CustomerDemographics = new HashSet<CustomerDemographic>() , CompanyName = "Oklahoma City Thunder", ContactName = "Kevin Durant", ContactTitle = "current top basket ball player", Address = "35 test row", City = "Oklahoma City", Region = "Oklahoma", PostalCode = "480290", Country = "USA", Phone = "304923", Fax = "33325" }
};
// Convert the list to an IQueryable list
IQueryable<Customer> queryableListOfCustomerInMemoryData = listOfCustomers.AsQueryable();
// Let us create a Mocked DbSet object.
Mock<DbSet<BlahBlahExample.Domain.Objects.Customer>> mockDbSet = new Mock<DbSet<BlahBlahExample.Domain.Objects.Customer>>();
// Force DbSet to return the IQueryable members
// of our converted list object as its
// data source
mockDbSet.As<IQueryable<BlahBlahExample.Domain.Objects.Customer>>().Setup(m => m.Provider).Returns(queryableListOfCustomerInMemoryData.Provider);
mockDbSet.As<IQueryable<BlahBlahExample.Domain.Objects.Customer>>().Setup(m => m.Expression).Returns(queryableListOfCustomerInMemoryData.Expression);
mockDbSet.As<IQueryable<BlahBlahExample.Domain.Objects.Customer>>().Setup(m => m.ElementType).Returns(queryableListOfCustomerInMemoryData.ElementType);
mockDbSet.As<IQueryable<BlahBlahExample.Domain.Objects.Customer>>().Setup(m => m.GetEnumerator()).Returns(queryableListOfCustomerInMemoryData.GetEnumerator());
mockDbSet.Setup(m => m.Add(It.IsAny<Customer>())).Callback<Customer>(listOfCustomers.Add);
Mock<BlahBlahAuditMappingProvider> jsAudtMppngPrvdr = new Mock<BlahBlahAuditMappingProvider>();
Mock<BlahBlahDataContext> fctry = new Mock<BlahBlahDataContext>(jsAudtMppngPrvdr.Object);
Mock<BlahBlahDataContext> qryCtxt = new Mock<BlahBlahDataContext>();
Mock<BlahBlahAuditContext> audtCtxt = new Mock<BlahBlahAuditContext>();
Mock<BlahBlahDataContext> mockedReptryCtxt = new Mock<BlahBlahDataContext>();
mockedReptryCtxt.Setup(q => q.Customers).Returns(mockDbSet.Object);
mockedReptryCtxt.Setup(q => q.Set<Customer>()).Returns(mockDbSet.Object);
mockedReptryCtxt.CallBase = true;
DbSet<Customer> inMemoryDbSetCustomer = mockedReptryCtxt.Object.Set<Customer>();
In the next excerpt of code( which is our "Code Under Test"), I add a new Customer to the existing In-Memory Data, and then Invoke SaveChanges on the Mocked Object.
Customer returnCust = (Customer)(mockedReptryCtxt.Object.Set<Customer>().Add(new Customer { CustomerID = "4 ", Orders = new HashSet<Order>(), CustomerDemographics = new HashSet<CustomerDemographic>(), CompanyName = "Kolkota Knights", ContactName = "Sachin Tendulkar", ContactTitle = "current top cricket player", Address = "35 test row", City = "Kolkota", Region = "West Bengal", PostalCode = "3454534", Country = "India", Phone = "304923", Fax = "33325" }));
mockedReptryCtxt.Object.SaveChanges();
Later on in the code, I have the following excerpt of code where _context.Set() will return the In-Memory Data DBSet that we created previously
var query = _context.Set<TEntity>().AsQueryable();
if (typeof(TEntity).Name.Contains("Audit"))
{
return query;
}
if (includes != null && includes.Any())
{
foreach (var include in includes)
{
query = query.Include(include);
}
}
List<TEntity> resultsAsList = query.ToList(); // Error Thrown When using ToList()
var results = resultsAsList.AsQueryable();
When we invoke ToList(), it Throws the following Error:
System.InvalidOperationException was unhandled by user code
HResult=-2146233079
Message=Collection was modified; enumeration operation may not execute.
Source=mscorlib
StackTrace:
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
at System.Collections.Generic.List`1.Enumerator.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at BlahBlah.Framework.EntityFramework.EntityFrameworkRepository`1.ConcreteQuery(List`1 includes) in d:\EMIS\BlahBlah Framework\BlahBlahFrameworkLightweight\BlahBlah.Framework.EntityFramework\EntityFrameworkRepository.c s:line 51
at Castle.Proxies.EntityFrameworkRepository`1Proxy.ConcreteQuery_callback(List`1 includes)
at Castle.Proxies.Invocations.EntityFrameworkRepository`1_ConcreteQuery.InvokeMethodOnTarget()
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Moq.Proxy.CastleProxyFactory.CallContext.InvokeBase()
at Moq.InvokeBase.HandleIntercept(ICallContext invocation, InterceptorContext ctx, CurrentInterceptContext localctx)
at Moq.Interceptor.Intercept(ICallContext invocation)
at Moq.Proxy.CastleProxyFactory.Interceptor.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.EntityFrameworkRepository`1Proxy.ConcreteQuery(List`1 includes)
at BlahBlah.Framework.Core.Repository.BaseRepository`1.Query(List`1 includes) in d:\EMIS\BlahBlah Framework\BlahBlahFrameworkLightweight\BlahBlah.Framework.Core\Repository\BaseRepository.cs:line 149
at Castle.Proxies.EntityFrameworkRepository`1Proxy.Query_callback(List`1 includes)
at Castle.Proxies.Invocations.IRepository`1_Query.InvokeMethodOnTarget()
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Moq.Proxy.CastleProxyFactory.CallContext.InvokeBase()
at Moq.InvokeBase.HandleIntercept(ICallContext invocation, InterceptorContext ctx, CurrentInterceptContext localctx)
at Moq.Interceptor.Intercept(ICallContext invocation)
at Moq.Proxy.CastleProxyFactory.Interceptor.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.EntityFrameworkRepository`1Proxy.Query(List`1 includes)
at BlahBlah.Test.Unit.CntrlrsTests.CustomerControllerTest.Test_Creation_Of_Customer_Using_Constructor_Of _Customer_Controller_That_Expects_Arguments() in d:\EMIS\BlahBlah Framework\BlahBlahFrameworkLightweight\BlahBlah.Test.Unit\CntrlrsTests\CustomerControllerTest.cs:line 278
InnerException:
What steps do we need to take in order to stop the said error from being thrown( preferably without Changing too much of our Code Under Test)?
I had this problem as well but not iterating over the collection isn't really an option for me. After some thought, I did figure out a solution. The issue is that the mock sets up the various IQueryable properties off of a fixed IQueryable object from the original list. That causes any modification of that list to invalidate the corresponding IQueryable. The solution is to get a new IQueryable on each access using a lambda with Moq.
Here's the helper function I created to make mocking out DBSets easier, using the described technique.
public static Mock<DbSet<T>> MockDbSet<T>(List<T> list) where T : class
{
var mockSet = new Mock<DbSet<T>>();
mockSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(() => list.AsQueryable().Provider);
mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(() => list.AsQueryable().Expression);
mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(() => list.AsQueryable().ElementType);
mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => list.GetEnumerator());
mockSet.Setup(m => m.Add(It.IsAny<T>())).Callback((T x) => list.Add(x));
mockSet.Setup(m => m.AddRange(It.IsAny<IEnumerable<T>>())).Callback((IEnumerable<T> x) => list.AddRange(x));
mockSet.Setup(m => m.Remove(It.IsAny<T>())).Callback((T x) => list.Remove(x));
mockSet.Setup(m => m.RemoveRange(It.IsAny<IEnumerable<T>>())).Callback((IEnumerable<T> x) => list.RemoveAll(x.Contains));
return mockSet;
}
Edit: Added AddRange, Remove, RemoveRange since why not...
Edit 2: Correction for RemoveRange
I found a really Clumsy Solution:
List<TEntity> tempList = new List<TEntity>();
for (int i = query.Count() - 1; i >= 0; i--)
{
tempList.Add(query.ElementAt(i));
}
List<TEntity> resultsAsList = tempList.ToList();
var results = resultsAsList.AsQueryable();
In the aforementioned code, it is important to use a for loop with an index to go through the DBSet instance. Furthermore, in the loop, you add each element to a List. ( Basically, it's important to Avoid using the Iterator)

Why is the DBSet Add failing, and also destroying the existing Customer entries in the DBSet?

Our programming involves some Mock testing using In Memory Data.
// Let us create some in-memory data
// Create a list of Customer
List<Customer> listOfCustomers = new List<BlahProjectBlahExample.Domain.Objects.Customer>()
{ new Customer { CustomerID = "1 ", CompanyName = "Chicago Bulls", ContactName = "Michael Jordan", ContactTitle = "top basket ball player", Address = "332 testing lane", City = "Chicago", Region = "Illinois", PostalCode = "484894", Country = "USA", Phone = "3293993", Fax = "39393" },
new Customer { CustomerID = "2 ", CompanyName = "Miami Heat", ContactName = "Lebron James", ContactTitle = "second best basket ball player", Address = "90 test street", City = "Miami", Region = "Florida", PostalCode = "4869394", Country = "USA", Phone = "3293213", Fax = "33393" },
new Customer { CustomerID = "3 ", CompanyName = "Oklahoma City Thunder", ContactName = "Kevin Durant", ContactTitle = "current top basket ball player", Address = "35 test row", City = "Oklahoma City", Region = "Oklahoma", PostalCode = "480290", Country = "USA", Phone = "304923", Fax = "33325" }
};
// Convert the list to an IQueryable list
IQueryable<Customer> queryableListOfCustomerInMemoryData = listOfCustomers.AsQueryable();
// Let us create a Mocked DbSet object.
Mock<DbSet<BlahProjectBlahExample.Domain.Objects.Customer>> mockDbSet = new Mock<DbSet<BlahProjectBlahExample.Domain.Objects.Customer>>();
// Force DbSet to return the IQueryable members
// of our converted list object as its
// data source
mockDbSet.As<IQueryable<BlahProjectBlahExample.Domain.Objects.Customer>>().Setup(m => m.Provider).Returns(queryableListOfCustomerInMemoryData.Provider);
mockDbSet.As<IQueryable<BlahProjectBlahExample.Domain.Objects.Customer>>().Setup(m => m.Expression).Returns(queryableListOfCustomerInMemoryData.Expression);
mockDbSet.As<IQueryable<BlahProjectBlahExample.Domain.Objects.Customer>>().Setup(m => m.ElementType).Returns(queryableListOfCustomerInMemoryData.ElementType);
mockDbSet.As<IQueryable<BlahProjectBlahExample.Domain.Objects.Customer>>().Setup(m => m.GetEnumerator()).Returns(queryableListOfCustomerInMemoryData.GetEnumerator());
Mock<BlahProjectBlahDataContext> mockedReptryCtxt = new Mock<BlahProjectBlahDataContext>();
mockedReptryCtxt.Setup(q => q.Customers).Returns(mockDbSet.Object);
mockedReptryCtxt.Setup(q => q.Set<Customer>()).Returns(mockDbSet.Object);
mockedReptryCtxt.CallBase = true;
DbSet<Customer> inMemoryDbSetCustomer = mockedReptryCtxt.Object.Set<Customer>();
In the following code, I used a loop to see the contents of the inMemoryDbSetCustomer, and it contained the expected data.
Customer something;
foreach (var entry in inMemoryDbSetCustomer)
{
something = entry as Customer;
}
Sadly, when I try to add a new customer,
1) the inMemoryDbSetCustomer fails to add the customer
2) the inMemoryDbSetCustomer.Add(someCust) returns NULL
3) the inMemoryDbSetCustomer seems to have lost all it's other Customer entries.
Customer someCust = new Customer { CustomerID = "4 ", CompanyName = "Kolkota Knights", ContactName = "Sachin Tendulkar", ContactTitle = "current top cricket player", Address = "35 test row", City = "Kolkota", Region = "West Bengal", PostalCode = "3454534", Country = "India", Phone = "304923", Fax = "33325" };
try
{
Customer returnCust = (Customer)(inMemoryDbSetCustomer.Add(someCust));
}
catch(Exception ex ){
}
Why is the DBSet Add failing, and also destroying the existing Customer entries in the DBSet?
Update With Answer
Thanks to #Werlang suggestion. The following code addition helped:
mockDbSet.Setup(m => m.Add(It.IsAny<Customer>()))
.Callback<Customer>((Customer c) => { listOfCustomers.Add(c); })
.Returns((Customer c) => c);
Also, if you mocking DBSets with Moq Framework like I am then the following stackoverflow posting will be helpful because you might face a similar problem:
What steps to get rid of Collection was modified; enumeration operation may not execute. Error?
You've mocked the queryable to return a fixed set of data, when accessed via IQueryable. But Add's are maintained in a separated list on DbContext internal in the form of DbEntry's.
I suggest you to mock the Add() method too, addind the new element to mocked array (listOfCustomers).

UnitTesting EF6 with OfType<T>

I am trying to follow the guidelines provided http://msdn.microsoft.com/en-us/library/dn314429.aspx by Microsoft for Unittesting DbSets. All was going well - as they documented. Until I got to some code which works with a inheritance table. Since OfType() is an extension method, I cannot figure out how to create a Mock which will work to keep my code testable.
To clarify: I am trying to Test My Service Layer, which take a DBContext which is Injected, and which exposes several DbSets. In particular, I have an abstract History class, which has concrete derived types of StaffHistory, ContactHistory, etc. As a result, I only have 1 DbSet on my Dbcontext, which is of type History. I then use the Extension method OfType to set the discriminator and query the particular type.
When I create a Mock DbSet all usually works fine, except the OfType extension method fails, reporting NullReference Exception.
Any ideas or tips?
Service Layer:
public IEnumerable<ContactHistory> GetContactHistory(int ContactId, int AgeInDays)
{
var age = DateTimeOffset.Now.AddDays(-Math.Abs(AgeInDays));
return context.History.OfType<ContactHistory>()
.Where(h => h.ContactId == ContactId && h.CreatedAt >= age)
.AsEnumerable();
}
Unit Test Code:
[TestMethod]
public void History_Returns_Limited_Results()
{
var testData = new List<ContactHistory> {
new ContactHistory {
ContactId = 1,
CreatedAt = DateTimeOffset.Now,
UserName = "UserA",
Action = "Action",
},
new ContactHistory {
ContactId = 4,
CreatedAt = DateTimeOffset.Now.AddDays(-61),
UserName = "UserA",
Action = "Action",
},
new ContactHistory {
ContactId = 4,
CreatedAt = DateTimeOffset.Now.AddDays(-60),
UserName = "UserA",
Action = "Action",
},
new ContactHistory {
ContactId = 4,
CreatedAt = DateTimeOffset.Now,
UserName = "UserA",
Action = "Action",
}
}.AsQueryable();
// Setup
var mockContext = new Mock<IPEContext>();
var mockSet = new Mock<IDbSet<History>>();
mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.Provider).Returns(testData.Provider);
mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.Expression).Returns(testData.Expression);
mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.ElementType).Returns(testData.ElementType);
mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.GetEnumerator()).Returns(testData.GetEnumerator());
mockContext.Setup(c => c.History).Returns(mockSet.Object);
// Test
var service = new HistoryService(mockContext.Object);
var historyFound = service.GetContactHistory(4, 60);
// Verify
Assert.IsNotNull(historyFound);
Assert.AreEqual(2, historyFound.Count());
}
Is there something flawed in my approach? Is there something flawed in how I have setup my mock? This was following the Microsoft Article I mentioned above so that I could test service logic acting on a DbSet. The only flaw seems to be the Extension Method - not sure how I should work around that.
OK - I have figured this out. Of course there was a simple answer, but one which eluded me, because I had already mapped the Linq Provider and all in as the Type IQueryable. If you are using the .OfType() method, your mock must return on the Untyped Queryable method.
Here is the test code to allow the Method to work properly:
[TestMethod]
public void History_Returns_Limited_Results()
{
var today = new DateTimeOffset(DateTime.Today, DateTimeOffset.Now.Offset);
var testData = new List<ContactHistory> {
new ContactHistory {
ContactId = 1,
CreatedAt = today,
UserName = "UserA",
Action = "Action",
},
new ContactHistory {
ContactId = 4,
CreatedAt = today.AddDays(-61),
UserName = "UserA",
Action = "Action",
},
new ContactHistory {
ContactId = 4,
CreatedAt = today.AddDays(-60),
UserName = "UserA",
Action = "Action",
},
new ContactHistory {
ContactId = 4,
CreatedAt = today,
UserName = "UserA",
Action = "Action",
}
}.AsQueryable();
// Setup
var mockContext = new Mock<IPEContext>();
var mockSet = new Mock<IDbSet<History>>();
mockSet.As<IQueryable>().Setup(m => m.Provider).Returns(testData.Provider);
mockSet.As<IQueryable>().Setup(m => m.Expression).Returns(testData.Expression);
mockSet.As<IQueryable>().Setup(m => m.ElementType).Returns(testData.ElementType);
mockSet.As<IQueryable>().Setup(m => m.GetEnumerator()).Returns(testData.GetEnumerator());
mockContext.Setup(c => c.History).Returns(mockSet.Object);
// Test
var service = new HistoryService(mockContext.Object);
var contact = new Person { ContactId = 4 };
var historyFound = service.GetContactHistory(contact, 60);
// Verify
Assert.IsNotNull(historyFound);
Assert.AreEqual(2, historyFound.Count());
}

EF 5 AddOrUpdate Duplicates data

This is the code in the Seed method:
var city = new City { Name = "A" };
var nh = new List<Neigh>
{
new Neigh { City = city, Name = "N1" },
new Neigh { City = city, Name = "N2" },
new Neigh { City = city, Name = "N3" },
//new Neigh { City = city, Name = "N4" },
};
context.Neighs.AddOrUpdate(
p => p.Name,
nh.ToArray()
);
After running update-database everything works as expected. I can run it multiple times without problem. However if at some point I uncomment the fourth neighborhood and run update-database again I end up with two records with city "A" and N4 is pointing to that city, while the rest point to the original city.
How do I prevent the inserting of a duplicate city if the list gets updated?
You must start the script by checking whether the city already exists:
var city = context.Cities.FirstOrDefault(c => c.Name == "A")
?? new City { Name = "A" };