I have the following structure of entities:
Route: -one-to-many-> :Stop: <-many-to-many-> :Child: <-many-to-many-> :Contact
And so I've defined the following named entity graphs at the top of each entity class so I can optimize my queries for how far down this heirarchy I'll need to travel:
Route:
#NamedEntityGraphs({
#NamedEntityGraph(name = "Route.stop.child.contact",
attributeNodes = {
#NamedAttributeNode(value = "stops", subgraph = "Stop.child.contact")
}),
#NamedEntityGraph(name = "Route.stop.child",
attributeNodes = {
#NamedAttributeNode(value = "stops", subgraph = "Stop.child")
}),
#NamedEntityGraph(name = "Route.stop",
attributeNodes = {
#NamedAttributeNode(value = "stops", subgraph = "Stop")
})
})
public class Route {...}
Stop:
#NamedEntityGraphs({
#NamedEntityGraph(name = "Stop.child.contact",
attributeNodes = {
#NamedAttributeNode(value = "children", subgraph = "Child.contact")
}),
#NamedEntityGraph(name = "Stop.child",
attributeNodes = {
#NamedAttributeNode(value = "children", subgraph = "Child")
}),
#NamedEntityGraph(name = "Stop", attributeNodes = {})
})
public class Stop {...}
Child:
#NamedEntityGraphs({
#NamedEntityGraph(name = "Child.contact",
attributeNodes = {
#NamedAttributeNode(value = "contacts", subgraph = "Contact")
}),
#NamedEntityGraph(name = "Child", attributeNodes = {})
})
public class Child {...}
Contact:
#NamedEntityGraphs({#NamedEntityGraph(name = "Contact", attributeNodes = {})})
public class Contact {...}
And I use them in my Repository class as such:
#EntityGraph(value = "Route.stop.child.contact", type = EntityGraph.EntityGraphType.LOAD)
Optional<Route> findRouteStopsChildrenContactsByRouteId(short routeId);
However, I can see no join queries being made, and a lazyinit exception is thrown when I try to access children of stops. My understanding was that this is how entity graphs can be used to optimize queries (i.e. n+1 problem when I have to fetch children for each individual stop), but I'm having no luck getting it to work.
Any advice as to what I'm doing wrong?
Try this one it worked for me.
#NamedEntityGraph(name = "Book.details", attributeNodes = #NamedAttributeNode("reviews"))
#Table(name = "Book")
public class Book implements Serializable
{
#OneToMany(cascade = CascadeType.ALL , mappedBy = "book" , fetch = FetchType.EAGER)
//#OrderBy("no ASC")
private List<Review> reviews ;
}
2) Get Record (internally use left outer join).
#EntityGraph(value = "Book.details", type = EntityGraphType.FETCH)
List<Book> getBooksByAuthName(String aname);
Related
How would I make self.character.data().bank the same to all instances of the class
even when using the function setBank? currently when using setBank it only updates self.character.data().bank on the one instance if it makes sense
_G.GetUser = {
users = {},
users_group = {},
userData = {},
CurrentCharacter = {}
}
_G.GetUserMethods = {}
GetUserMethods.__call = function(self, source)
local o = setmetatable({}, {
__index = self
})
o.src = source
o.id = self.users[o.src]
o.rank = self.users_group[o.src]
return o
end
GetUserMethods.__index = {
getCurrentCharacter = function(self)
self.character = {}
self.character.id = self.CurrentCharacter[self.id]
self.character.data = function()
return self.userData[self.character.id]
end
self.character.setBank = function(v)
if self.character.data() then
self.character.data().bank = v
end
end
self.character.getBank = function()
if self.character.data() then
return self.character.data().bank
end
return nil
end
return self.character
end
}
setmetatable(GetUser, GetUserMethods)
Replace
importClass {'getuser'}
with
if not _G.GetUser then
importClass {'getuser'}
end
in each file.
*SOLUTION IS IN THE FIRST ANSWER
I'm pretty noob using SimpleXML Converter so models and annotations may be wrong.
This is the XML I receive:
<?xml version="1.0" encoding="UTF-8"?>
<cards-summary-response xmlns="http:/mywebpage.com/rest-api">
<card-summary>
<identifier>51641C1B23931</identifier>
<display-name>Debit Card</display-name>
<program-name>plastic_debit</program-name>
<status>Blocked</status>
</card-summary>
<card-summary>
<identifier>4E1BDFCC1D6</identifier>
<display-name>Virtual Debit</display-name>
<program-name>virtual_debit</program-name>
<status>Active</status>
</card-summary>
</cards-summary-response>
My models:
CardSummaryResponse.kt
#Root(strict = false, name = "cards-summary-response")
data class CardSummaryResponse constructor(
#ElementList(
required = false,
name = "card-summary",
entry = "card-summary",
inline = true,
empty = true
)
var cardsSummaryList: MutableList<CardSummary>? = null
)
CardSummary.kt
#Root(name = "card-summary")
data class CardSummary #JvmOverloads constructor(
#field:Element(name = "identifier", required = true)
var identifier: String = "",
#field:Element(name = "status", required = true)
var status: String = ""
)
API configuration:
retrofit = Retrofit.Builder()
.addConverterFactory(SimpleXmlConverterFactory.createNonStrict(
Persister(AnnotationStrategy())
)
)
.baseUrl(CallsConfiguration.BASE_URL_WIRECARD)
.client(clientBuilder.build())
.build()
service = retrofit.create(RetrofitInterface::class.java)
And RetrofitInterface (this class is in Java):
#GET("webservices/wd-test.phtml")
Call<CardSummaryResponse> getCardsSummary();
I'm always getting the same exception:
java.lang.Error: org.simpleframework.xml.core.ConstructorException:
Parameter 'card-summary' does not have a match in class
com.app.account.model.CardSummaryResponse
Any suggestions?
I have managed to make it work using the following models:
CardSummaryResponse.tk
#Root(strict = false, name = "cards-summary-response")
data class CardSummaryResponse constructor(
#field:ElementList(
required = false,
name = "card-summary",
entry = "card-summary",
inline = true,
empty = true
)
var cardsSummaryList: MutableList<CardSummary>? = null
)
CardSummary.tk
#Root(name = "card-summary")
data class CardSummary constructor(
#field:Element(name = "identifier", required = true)
var identifier: String = "",
#field:Element(name = "status", required = true)
var status: String = ""
)
In my case, I was using 'val' in the data class. After spending 3 hours, I found the solution: just replace 'val with 'var' and give the default value.
Here are my data classes that are working fine after the solution:
sealed class Feeds {
#Root(name = "rss", strict = false)
data class RssFeed constructor(#field:Element(name = "channel") var channel: RssChannel? = null) :
Feeds()
#Root(name = "channel", strict = false)
data class RssChannel constructor(
#field:ElementList(
name = "item",
inline = true,
required = false
) var item: List<RssItem>? = null
) : Feeds()
#Root(name = "item", strict = false)
data class RssItem constructor(
#field:Element(name = "title") var title: String = "",
#field:Element(name = "description") var description: String = "",
#field:Element(name = "link") var link: String = ""
) : Feeds()
}
Happy Coding!!!
I use xUnit as test runner in my asp.net core application.
Here is my test theory:
[Theory(DisplayName = "Search advisors by advisorId"),
ClassData(typeof(SearchAdvisorsByIdTestData))]
public async void SearchAdvisors_ByAdvisorId(int brokerDealerId, FilterParams filter)
{
// Arrange
var _repositoryMock = new Mock<IRepository>();
// Do this section means we bypass the repository layer
_repositoryMock
.Setup(x => x.SearchAdvisors(filter.CID.Value, new AdvisorSearchOptions
{
SearchKey = filter.SeachKey,
AdvisorId = filter.AdvisorId,
BranchId = filter.BranchId,
City = filter.City,
Skip = filter.Skip,
Limit = filter.Limit,
RadiusInMiles = filter.Limit,
Longitude = filter.Longitude,
Latitude = filter.Latitude
}))
.Returns(Task.FromResult<SearchResults<Advisor>>(
new SearchResults<Advisor>()
{
Count = 1,
Limit = 0,
Skip = 0,
ResultItems = new List<SearchResultItem<Advisor>>() {
//some initialize here
}
})
);
_advisorService = new AdvisorService(_repositoryMock.Object, _brokerDealerRepositoryMock, _brokerDealerServiceMock);
// Action
var model = await _advisorService.Search(brokerDealerId, filter);
Assert.True(model.AdvisorResults.Count == 1);
Assert.True(model.AdvisorResults[0].LocationResults.Count > 0);
}
The service like this
public async Task<ViewModelBase> Search(int brokerDealerId, FilterParams filter)
{
var opts = new AdvisorSearchOptions
{
SearchKey = filter.SeachKey,
AdvisorId = filter.AdvisorId,
BranchId = filter.BranchId,
City = filter.City,
Skip = filter.Skip,
Limit = filter.Limit,
RadiusInMiles = filter.Limit,
Longitude = filter.Longitude,
Latitude = filter.Latitude
};
var searchResults = await _repository.SearchAdvisors(filter.CID.Value, opts); // line 64 here
if (searchResults.Count == 0 && Utils.IsZipCode(filter.SeachKey))
{
}
//Some other code here
return model;
}
The issue was after run line 64 in the service. I always get null value of searchResults although I already mocked _repository in the test.
What was my wrong there?
Thank in advance.
Argument matcher for SearchAdvisors() mock does not work because you pass different instances of AdvisorSearchOptions. First instance is created in _repositoryMock.Setup() statement and the second one is created in Search() method itself.
There are several ways to fix this problem:
1.If you don't care about verifying whether instance of AdvisorSearchOptions passed to repository is filled correctly, just use It.IsAny<AdvisorSearchOptions>() matcher in mock setup:
_repositoryMock.Setup(x => x.SearchAdvisors(filter.CID.Value, It.IsAny<AdvisorSearchOptions>()))
.Returns(/*...*/);
2.In previous case the test will not verify that AdvisorSearchOptions is filled correctly. To do this, you could override Object.Equals() method in AdvisorSearchOptions class so that mock call will match for different instances:
public class AdvisorSearchOptions
{
// ...
public override bool Equals(object obj)
{
var cmp = obj as AdvisorSearchOptions;
if (cmp == null)
{
return false;
}
return SearchKey == cmp.SearchKey && AdvisorId == cmp.AdvisorId &&
/* ... compare all other fields here */
}
}
3.Another way to verify object passed to mock is to save the instance via Mock callback and then compare required fields:
AdvisorSearchOptions passedSearchOptions = null;
_repositoryMock
.Setup(x => x.SearchAdvisors(filter.CID.Value, It.IsAny<AdvisorSearchOptions>()))
.Returns(Task.FromResult<SearchResults<Advisor>>(
new SearchResults<Advisor>()
{
Count = 1,
Limit = 0,
Skip = 0,
ResultItems = new List<SearchResultItem<Advisor>>() {
//some initialize here
}
})
)
.Callback<int, AdvisorSearchOptions>((id, opt) => passedSearchOptions = opt);
// Action
// ...
Assert.IsNotNull(passedSearchOptions);
Assert.AreEqual(filter.SearchKey, passedSearchOptions.SearchKey);
Assert.AreEqual(filter.AdvisorId, passedSearchOptions.AdvisorId);
// Check all other fields here
// ...
What is the best way for mapping collection of objects in NHibernate?
Now I am using bags, but maybe another approach can be more efficient?
Before wore Bag and ClassMapping, something very similar to this:
Bag(am => am.AlumnoMateriaId, map =>
{
map.Table("Calificacion");
map.Cascade(Cascade.None);
map.Key(k =>
{
k.Column("AlumnoId");
k.ForeignKey("FK_Calificacion_AlumnoMateria");
});
}, rel => rel.ManyToMany(p => p.Column("AlumnoId")));
Now Use the NHibernate.Mapping.Attributes, and a class would look like:
using NHMA = NHibernate.Mapping.Attributes;
[NHMA.Class(Table = " Calificacion ")]
public class Calificacion
{
[NHMA.Id(0, Name = "id", TypeType = typeof(Int32), Column = "Id", Access = "field")]
[NHMA.Generator(1, Class = "native")]
public Int32 id;
public virtual Int32 Id
{
get { return id; }
set { id = value; }
}
[NHMA.ManyToOne(2, Name = "calificacion", Access = "field", Column = "CalificacionID",
Class = "Calificacion", ClassType = typeof(Calificacion),
ForeignKey = "FK_Calificacion_Alumno", NotNull = false)]
private Calificacion calificaion;
public virtual Calificacion Calificaion
{
get { return calificaion; }
set { calificaion = value; }
}
[NHMA.Property(Name = "nombre", Access = "field", Column = "Nombre", Length = 50)]
private string nombre;
public virtual string Nombre
{
get { return nombre; }
set { nombre = value; }
}
}
I'm trying to archive my search results for a term by
Using the Bing API in an async controller
Inserting them into database using Entity Framework
using the Bing API and insert them into a database using entity framework. For whatever reason it is returning 50 results, but then it enters 100 results into the database.
My Controller Code:
public class DHWebServicesController : AsyncController
{
//
// GET: /WebService/
private DHContext context = new DHContext();
[HttpPost]
public void RunReportSetAsync(int id)
{
int iTotalCount = 1;
AsyncManager.OutstandingOperations.Increment(iTotalCount);
if (!context.DHSearchResults.Any(xx => xx.CityMarketComboRunID == id))
{
string strBingSearchUri = #ConfigurationManager.AppSettings["BingSearchURI"];
string strBingAccountKey = #ConfigurationManager.AppSettings["BingAccountKey"];
string strBingUserAccountKey = #ConfigurationManager.AppSettings["BingUserAccountKey"];
CityMarketComboRun cityMarketComboRun = context.CityMarketComboRuns.Include(xx => xx.CityMarketCombo).Include(xx => xx.CityMarketCombo.City).First(xx => xx.CityMarketComboRunID == id);
var bingContainer = new Bing.BingSearchContainer(new Uri(strBingSearchUri));
bingContainer.Credentials = new NetworkCredential(strBingUserAccountKey, strBingAccountKey);
// now we can build the query
Keyword keyword = context.Keywords.First();
var bingWebQuery = bingContainer.Web(keyword.Name, "en-US", "Moderate", cityMarketComboRun.CityMarketCombo.City.Latitude, cityMarketComboRun.CityMarketCombo.City.Longitude, null, null, null);
var bingWebResults = bingWebQuery.Execute();
context.Configuration.AutoDetectChangesEnabled = false;
int i = 1;
DHSearchResult dhSearchResult = new DHSearchResult();
List<DHSearchResult> lst = new List<DHSearchResult>();
var webResults = bingWebResults.ToList();
foreach (var result in webResults)
{
dhSearchResult = new DHSearchResult();
dhSearchResult.BingID = result.ID;
dhSearchResult.CityMarketComboRunID = id;
dhSearchResult.Description = result.Description;
dhSearchResult.DisplayUrl = result.DisplayUrl;
dhSearchResult.KeywordID = keyword.KeywordID;
dhSearchResult.Created = DateTime.Now;
dhSearchResult.Modified = DateTime.Now;
dhSearchResult.Title = result.Title;
dhSearchResult.Url = result.Url;
dhSearchResult.Ordinal = i;
lst.Add(dhSearchResult);
i++;
}
foreach (DHSearchResult c in lst)
{
context.DHSearchResults.Add(c);
context.SaveChanges();
}
AsyncManager.Parameters["message"] = "The total number of results was "+lst.Count+". And there are " + context.DHSearchResults.Count().ToString();
}
else
{
AsyncManager.Parameters["message"] = "You have already run this report";
}
AsyncManager.OutstandingOperations.Decrement(iTotalCount);
}
public string RunReportSetCompleted(string message)
{
string str = message;
return str;
}
}
Here is how I am calling it from my asp.net mvc 4 page.
#Ajax.ActionLink("Run Report", "GatherKeywordsFromBing", "DHWebServices",
new { id=item.CityMarketComboRunID},
new AjaxOptions { OnSuccess = "ShowNotifier();", UpdateTargetId = "TopNotifierMessage", HttpMethod = "POST", InsertionMode = InsertionMode.Replace, LoadingElementId = strCityMarketComboProgressID, LoadingElementDuration = 1000 },
new { #class = "ViewLink" })
<span class="ProgressIndicator" id="#strCityMarketComboProgressID"><img src="#Url.Content("~/Content/img/SmallBall.gif")" alt="loading" /></span>
For whatever reason all of
Try saving only once:
foreach (DHSearchResult c in lst)
{
context.DHSearchResults.Add(c);
}
context.SaveChanges();
Also there's nothing asynchronous in your code, so there's no point of using asynchronous controller. Not only that it won't improve anything but it might make things worse.