Is there a way to define a connection to a new Solr core on the fly, based on dynamic data?
We have a scenario where our Solr installation has multiple Cores/Indexes for the same type of document, separated by date (so a given week's documents will be on Index 1, the previous week's on Index 2, etc).
So when I receive my query, I check to see the required date range, and based on it, I want to query a specific core. I don't know in advance, at startup, which cores I will have, since new ones can be created dynamically during runtime.
Using the built-in ServiceLocation provider, there's no way to link two different Cores to the same document class. But even if I use a different DI container (currently Autofac in my case), I still need to specify all Core URLs in advance, during component registration.
Is there a way to bypass it except for always creating a new Autofac Container, generating the ISolrOperation<> class from it, and releasing it until the next time I need to connect to a core?
Mauricio Scheffer (developer of Solr.Net)'s comment confirmed that there's no built-in support for connecting to different index URLs on the fly. So instead of instantiating the internal objects myself, I used a hack on top of my existing Autofac based DI container:
public ISolrOperations<TDocument> ConnectToIndex<TDocument>(string indexUrl)
{
// Create a new AutoFac container environment.
ContainerBuilder builder = new ContainerBuilder();
// Autofac-for-Solr.Net config element.
var cores = new SolrServers
{
new SolrServerElement
{
Id = indexUrl,
DocumentType = typeof (TDocument).AssemblyQualifiedName,
Url = indexUrl,
}
};
// Create the Autofac container.
builder.RegisterModule(new SolrNetModule(cores));
var container = builder.Build();
// Resolve the SolrNet object for the URL.
return container.Resolve<ISolrOperations<TDocument>>();
}
Related
Trying to migrate an existing solution away from the deprecated Microsoft.Xrm.Client namespace to just use the generated service context from CrmSvcUtil using CrmSDK 9.0.0.5.
Previously we were using Microsoft.Xrm.Client.CodeGeneration.CodeCustomization to get a lazily loaded context.
I have two copies of the same solution and have been working through some of the API changes.
I have enabled Proxy Types
client.OrganizationServiceProxy.EnableProxyTypes();
Which to my understanding switched it to act in a lazily-loaded manner. However, none of the navigation properties are loading as expected.
The few blog posts that I've found around this shift to CrmServiceClient etc suggest that even without lazy loading I should be able to load the property manually with a call to Entity.LoadProperty() which will either load the property or refresh the data. However, after doing that the navigation property is still null (specifically I'm trying to use a Contact navigation property). When I look through the RelatedEntities collection it is also empty.
I know that the entity has a related contact item as if I use a context generated with Microsoft.Xrm.Client.CodeGeneration.CodeCustomization it returns it and I can also see it in CRM itself using an advanced search.
var connectionUri = ConfigurationManager.ConnectionStrings["Xrm"].ConnectionString;
var client = new CrmServiceClient(connectionUri);
client.OrganizationServiceProxy.EnableProxyTypes();
var context = new XrmServiceContext(client);
var result = context.new_applicationSet.FirstOrDefault(x => x.new_applicantid.Id == CurrentUserId);
//result.Contact is null
context.LoadProperty(result, "Contact");
//result.Contact is still null
//result.RelatedEntities is empty
One of the requirement is to update the document with new content also delete the old document. document Id and other properties of the previous document should be pointing to the new document with new content.
There any sample snippet to do the same thanks.
I did not quite get it whether you need to create a new document or a new version of the existing document. Properties can be copied automatically to the newly created version, thus using versioning seems more natural here. To accomplish this:
// check out the document
Document currentVersion = .. // reference to existing document
currentVersion.checkout(ReservationType.EXCLUSIVE, null, null, null);
currentVersion.save(RefreshMode.REFRESH);
// obtain the reservation object (new version in progress)
newVersion = (com.filenet.api.core.Document) documentObject.get_Reservation();
// set content
InputStream inputStream = .. // obtain input stream with content
ContentElementList contentElements = Factory.ContentElement.createList();
ContentTransfer contentTransfer = Factory.ContentTransfer.createInstance();
contentTransfer.setCaptureSource(inputStream);
contentTransfer.set_RetrievalName("content name");
contentTransfer.set_ContentType("proper MIME type");
contentElements.add(contentTransfer);
newVersion.set_ContentElements(contentElements);
newVersion.checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY, CheckinType.MINOR_VERSION);
newVersion.save(RefreshMode.NO_REFRESH);
// deleting obsolete version
currentVersion.delete();
currentVersion.save(RefreshMode.NO_REFRESH);
Properties that are designated for transfer to the reservation (default mode for all non-object properties) will make it into the new version, which effectively is the reservation object once it is persisted.
One thing to note is that the new version cannot have the same ID as the previous one, since each version is a distinct object. To use the same ID you would need to create a new document having this ID and copy properties manually (deleting the old document before persisting the new one).
UPDATE
Regarding atomic updates which must include several objects you have two options:
Update objects in batch
Use client-initiated JTA transaction (if you connect using EJB transport)
You can read about these in the documentation: Batch Concepts, Client-Initiated Transactions.
Using batches is more conventional way that you would normally use unless you have complex update scenario.
I have records marked up as "IsArchived". I am looking for an expedient way to exclude these records from a current MVC3 / EF3 web application.
Is there a way to add some kind of "IsArchived" filter to the EF layer. In my case I have a seperate Model project with tables/views represented as POCO entities, and the mappings contained in the CSDL and SSDL files.
Huge thanks for any assistance.
EDIT:
I am using "ObjectContext" and not "DbContext", mainly due to the Data Modelling tool that I am using. This tool creates the context and POCO files.
I am wondering whether I can edit this context file like the following:
public ObjectSet<StdOrg> StdOrg
{
get
{
if ((_StdOrg == null))
{
_StdOrg = base.CreateObjectSet<StdOrg>("StdOrg");
// new line below. Got cast error tween both sides.
_StdOrg = (ObjectSet<StdOrg>) _StdOrg.Where(r => r.IsArchived == false);
}
return _StdOrg;
}
}
Take a look at this http://www.matthidinger.com/archive/2012/01/25/a-smarter-infrastructure-automatically-filtering-an-ef-4-1-dbset.aspx
Basically a filtering DBSet implementation that the example basically shows being used for Soft Delete. We use it without issue in our App.
However we are using DBcontext so not sure how this would work with Object Context or how it could be adapted
I’m building an MVC3 application with form authentication and a single hierarchical entity. The entity has a Region object as the “root” with several other objects. It looks something like:
Region->Language->objectA->objectB
Region->Application->….
Each user (other than administrators) is associated with single region. I'd like to limit the data loaded to the entity based on the user’s region. I’m not too familiar with EF. Is this appropriate or is there a better approach? How would I implement the best approach
You can certainly filter the data returned via Entity Framework. The code would look something like this:
using (MyContext ctx = new MyContext())
{
var filtered = (from r in ctx.Regions where SOME_CONDITIONS select r);
// Do stuff with filtered (which is an IEnumerable<Region>)
}
Note that you may need to use Include to load related objects, e.g.
ctx.Regions.Include("Language").Include("Application")
see http://msdn.microsoft.com/en-us/library/bb896272.aspx
I find that there are two ways at least to create a record in an entity like the following.
Common Part
var record = new someEntity()
{
attribute1="test1",
attribute2="test2"
};
var service = new OrganizationService("CrmConnectionString");
Part A
service.Create(record);
Part B
var orgContext = new OrganizationServiceContext(service);
orgContext.AddObject(record);
orgContext.SaveChanges();
What is the difference?And which is better?
Part A uses the raw create method of the organization service proxy. This operation directly creates the record.
Part B makes use of the OrganizationServiceContext, which implements the Unit of Work pattern. Your operations are not transmitted to the server until you call SaveChanges()
Which is better? It depends on your requirements. If you only want to create a record on the go -> use the service. If you do multiple things which form a logical unit take version B.