I am attempting to simply check a list of Managed Properties for a specific property. In theory, not difficult. In practice, it is proving to give me trouble. The first approach I found is as follows:
static void Main(string[] args)
{
try
{
string strURL = "http://<SiteName>";
Schema sspSchema = new Schema(SearchContext.GetContext(new SPSite(strURL)));
ManagedPropertyCollection properties = sspSchema.AllManagedProperties;
foreach (ManagedProperty property in properties)
{
if (property.Name.Equals("ContentType")
{
Console.WriteLine(property.Name);
}
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
This pulled back exactly what I wanted. However, the issue with this is that Visual Studio 2012 says that SearchContext is obsolete and depricated, and that I should use SearchServiceApplication instead. So I did some more searching and found the following:
SPServiceContext context = SPServiceContext.GetContext(SPServiceApplicationProxyGroup.Default, SPSiteSubscriptionIdentifier.Default);// Get the search service application proxy
var searchProxy = context.GetDefaultProxy(typeof(SearchServiceApplicationProxy)) as SearchServiceApplicationProxy;
if (searchProxy != null)
{
SearchServiceApplicationInfo ssai = searchProxy.GetSearchServiceApplicationInfo();
var application = SearchService.Service.SearchApplications.GetValue<SearchServiceApplication>(ssai.SearchServiceApplicationId);
var schema = new Schema(application);
ManagedPropertyCollection properties = schema.AllManagedProperties;
foreach (ManagedProperty property in properties)
{
if (property.Name.Equals("ContentType")
{
Console.WriteLine(property.Name);
}
}
}
The problem I run into with this is an EndpointNotFoundException.
I'm guessing I am just configuring the second option incorrectly as the first method can find everything just fine. Can anyone shed some light on anything obviously wrong that I am missing?
Any tips/hints will be appreciated!
This chunk of code should get you what you want.
foreach (SPService service in SPFarm.Local.Services)
{
if (service is SearchService)
{
SearchService searchService = (SearchService)service;
foreach (SearchServiceApplication ssa in searchService.SearchApplications)
{
Schema schema = new Schema(ssa);
foreach (ManagedProperty property in schema.AllManagedProperties)
{
if (property.Name == "ContentType")
{
//Handle here
}
}
}
}
}
Related
In my C# console application I am trying to update an account in CRM 2016. IsFaulted keeps returning true.
The error message it returns when I drill down is the following:
EntityState must be set to null, Created (for Create message) or Changed (for Update message).
Also in case it might cause the fault I have pasted my LINQ query at the bottom.
The answers I get from Google states either that I am mixing ServiceContext and ProxyService (which am not, I am not using it in this context). The others says that I am using context.UpdateObject(object) incorrectly, which I am not using either.
Update: Someone just informed me that the above error is caused because I am trying to return all the metadata and not just the updated data. Still I have no idea how to fix the error, but this information should be helpful.
private static void HandleUpdate(IOrganizationService crmService, List<Entity> updateEntities)
{
Console.WriteLine("Updating Entities: " + updateEntities.Count);
if (updateEntities.Count > 0)
{
try
{
var multipleRequest = new ExecuteMultipleRequest()
{
// Assign settings that define execution behavior: continue on error, return responses.
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = true,
ReturnResponses = true
},
// Create an empty organization request collection.
Requests = new OrganizationRequestCollection()
};
foreach (var account in updateEntities)
{
multipleRequest.Requests.Add(
new UpdateRequest()
{
Target = account
});
}
ExecuteMultipleResponse response = (ExecuteMultipleResponse)crmService.Execute(multipleRequest);
if (response.IsFaulted)
{
int failedToUpdateAccount = 0;
foreach (ExecuteMultipleResponseItem singleResp in response.Responses)
{
if (singleResp.Fault != null)
{
string faultMessage = singleResp.Fault.Message;
var account = ((UpdateRequest)multipleRequest.Requests[singleResp.RequestIndex]).Target;
Log.Error($"Error update acc.id: {account.Id}.Error: {singleResp.Fault.Message}.");
failedToUpdateAccount++;
}
}
Log.Debug($"Failed to update {failedToUpdateAccount} accounts.");
}
else
{
Log.Debug("Execute multiple executed without errors");
}
}
catch (Exception ex)
{
Log.Error($"Error while executing Multiplerequest", ex);
}
}
}
// LINQ below
private static List<Account> GetAllActiveCRMAccounts(CRM2011DataContext CRMcontext)
{
Console.WriteLine("Start Getting CRMExistingAccounts ....");
List<Account> CRMExisterendeAccounts = new List<Account>();
try
{
CRMExisterendeAccounts = (from a in CRMcontext.AccountSet
where a.StateCode == AccountState.Active
where a.anotherVariable == 1
select new Account()
{
my_var1 = a.myVar1,
my_var2 = a.myVar2,
AccountId = a.AccountId,
anotherVar = a.alsoThisVar,
}).ToList();
}
catch (FaultException ex)
{
Log.Debug($"GetCRMExistingAccounts Exception { ex.Message}");
Console.WriteLine("GetCRMExistingAccounts Exception " + ex.Message);
throw new Exception(ex.Message);
}
return CRMExisterendeAccounts;
}
And yes, my variables has different names in my system.
The query returns the object just fine with all the correct data.
You can work around this in one of two ways:
1) Create your CRM2011DataContext with the MergeOption set to MergeOption.NoTracking. Entities loaded from a context that is not tracking will have a null EntityState property.
2) You can create a copy of your Entity and save the copy.
I asked a similar question to this over on Unity3D Q&A, but I didn't get a response. I've finally got back round to this project and still have the same issue.
Link To Unity Question
I have searched, but I don't think I've hit the right keywords cause I still haven't found an answer that fits. Anyway, I will ask the question a different way and hopefully someone can point me in the right direction.
So below is the code that I have come up with, it's not the actual code in the game, but it does a good job at showing my problem.
Basically, in the build() method I want to check that both lists each contain the same type of tool, without actually hard coding the type. I don't care about the specific tool instance, just that it is of a certain type. The aim is that I can create new tools without having to modify the build method to incorporate these new types.
If there is a better way to do it I'm all ears.
Thanks
namespace TypeExample
{
class Tool
{
}
class Spanner : Tool
{
}
class Wrench : Tool
{
}
class Builder
{
List<Tool> toolsAvailable = new List<Tool>();
List<Tool> toolsRequired = new List<Tool>();
public Builder()
{
Spanner spanner = new Spanner();
Wrench wrench = new Wrench();
toolsRequired.Add(spanner);
toolsRequired.Add(wrench);
}
public void GiveTool(Tool tool)
{
toolsAvailable.Add(tool);
}
public void build()
{
// if true
Console.WriteLine("Building");
// else
Console.WriteLine("I don't have the tools to build!");
}
}
class Program
{
static void Main(string[] args)
{
Spanner spanner = new Spanner();
Wrench wrench = new Wrench();
Builder builder = new Builder();
builder.GiveTool(spanner);
builder.GiveTool(wrench);
builder.build();
Console.ReadLine();
}
}
}
Basicly you should get all the types from collections using Linq and then compair the result.
var toolsAvailableTypes = toolsAvailable.Select(t => t.GetType()).Distinct();
var toolsRequiredTypes = toolsRequired.Select(t => t.GetType()).Distinct();
if (toolsRequiredTypes.Except(toolsAvailableTypes).Any())
{
//building
}
It is not clear, should you compair only types of instruments or quantity also. My answer assume you don't care about quantity and you can build with one spanner when you require two.
-Update
To comply the requirement about subclasses (Sriram Sakthivel mentioned it) you can check if available tool type is subclass to required tool type so you can use any SpecialSpanner when you need a Spanner
var toolsAvailableTypes = toolsAvailable.Select(t => t.GetType()).Distinct().ToList();
var toolsRequiredTypes = toolsRequired.Select(t => t.GetType()).Distinct().ToList();
if (CanBuild(toolsAvailableTypes, toolsRequiredTypes))
{
Console.WriteLine("building");
}
else
{
Console.WriteLine("not enough minerals");
}
CanBuild method:
bool CanBuild(List<Type> toolsAvailableTypes, List<Type> toolsRequiredTypes)
{
foreach (var requiredType in toolsRequiredTypes)
{
bool isAvailable = toolsAvailableTypes.Any(availableType => availableType.IsSubclassOf(requiredType) || availableType == requiredType);
if (!isAvailable)
{
return false;
}
}
return true;
}
var reqdTypes = toolsRequired.Select(x => x.GetType());
var availableTypes = toolsAvailable.Select(x => x.GetType());
if (reqdTypes.Except(availableTypes).Any())
{
//Something exist in reqdTypes which is not in availableTypes
}
Note:This will fail if you provide more derived type than expected type. For example if you provide SpecialSpanner in place or Spanner this won't work.
Ok here is the deal. using my Model to raise the Child_Update() Method. I know it is not good but im just learing right now. Now i given my Business class as Parameter to Change the already given rows.
It's doin everything fine without any error Messages and there is also no null variable but it's not changing anything in the database.
here i'm using the selectedIndex to choose the right items to update
public void ExecuteAngestellte(object obj)
{
try
{
_selectedIndex.Child_Update(new Farbe { FarbauswahlNr = SelectedIndex.FarbauswahlNr, Kurztext = SelectedIndex.Kurztext, Ressource = SelectedIndex.Ressource, Vari1 = SelectedIndex.Vari1, Vari2 = SelectedIndex.Vari2 });
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
and here's the child update
public void Child_Update(Farbe data)
{
using (var ctx =Csla.Data.ObjectContextManager<TestDBEntities>.GetManager(EntitiesDatabase.Name))
{
var objectStateManager = ctx.ObjectContext.ObjectStateManager;
var _data = new Datenbank.Farbe();
_data.FarbauswahlNr = data.FarbauswahlNr;
_data.Kurztext = data.Kurztext;
_data.Ressource = data.Ressource;
_data.Var1 = data.Vari1;
_data.Vari2 = data.Vari2;
ctx.ObjectContext.SaveChanges();
}
}
thx for help
as far as I can tell, your _data is not part of the datacontext
I am not sure what the variables all mean so here is a simple update I use for a single record with entity framework
public void UpdateTable(int idRecord, YourContext Context)
{
MyRecord = Context.MyTable.Find(idRecord);
myRecord.Column = "New Value";
Context.SaveChanges();
}
so I think you need to do:
var MyData = ctx.ObjectContext.TableName.Find(id)
I am assuming you are using entity framework. Does this help?
I have a silverlight mvvm with ria project. I have a UI in which admin users can enter info to create new work orders. However, I am having trouble calling the db and adding a new record to the table. I have no code-behind for the UI, the controls are tied to the model through Commands and Command Parameters. So when a user clicks, 'Add new job' it comes here,
public class EditJobViewModel : ViewModelBase
{
private Job _job;
public Job CurrentJob
{
get { return _job; }
set
{
_job = value;
OnPropertyChanged("CurrentJob");
}
}
public ICommand NewJob
{
get
{
return new DelegateCommand(BeginNewJob, (o) => true);
}
}
public void BeginNewJob(object o)
{
_job = new Job();
//_job.JobNumber = _job.JobID.ToString();
_job.AssignedTo = App.userID;
_job.AddedBy = App.userID;
_job.FileTypeJob = "PDF";
_job.AddedTS = DateTime.Now;
_job.OpenDate = DateTime.Now;
BeginSave(o);
}
}
Where Im having trouble is creating a new record in the 'Job' table. On my breakpoint it returns all the columns it needs to, just not a new 'JobID' which is my primary key. This is how I was supposedly trying to create a new record.
public void BeginSave(object o)
{
if (!IsDesignTime)
{
try
{
if (CurrentJob.EntityState == EntityState.New)
{
CurrentJob.AddedBy = App.userID;
CurrentJob.AddedTS = DateTime.Now;
}
CurrentJob.UpdatedBy = App.userID;
CurrentJob.UpdatedTS = DateTime.Now;
// This is here because of a bug in infragistics grid/Entity Framework
foreach (JobFileType ft in CurrentJob.JobFileTypes)
{
if (ft.EntityState != EntityState.Unmodified)
(ft as IEditableObject).EndEdit();
}
foreach (JobTag tag in CurrentJob.JobTags)
{
if (tag.EntityState != EntityState.Unmodified)
(tag as IEditableObject).EndEdit();
}
//(CurrentJob as IEditableObject).EndEdit();
SubmitOperation s = _context.SubmitChanges();
if (s.HasError)
{ }
}
catch (Exception ex)
{ }
}
}
Except that it never hits the EntityState.new. That's just the way I thought to try it. Im thinking there a way to do it from the 'BeginNewJob' command but unable to find a way to create a new JobID or record in general. The Database already has 10000 records and has multiple users creating jobs, so I need a way to get the last job created (getMaxID()??) and increment appropriately, creating a new job on the spot.
İf you use guid type for id column, you will not need to find next id and this approach will decouple new objects from previous objects.
Ok, I am attempting to use this custom extension to perform an entity update. Right now it should update all properties and then all of its related ends (references). The problem is even though the entity with changes does have a related end with an entity key that is valid and correct (verified in the debugger its there). When the RelationshipManager gets it they key is null.. Anyone see anything wrong with this code?
public static void ApplyChanges(this ObjectContext context, EntityObject entityWithChanges)
{
if (entityWithChanges.EntityState == EntityState.Detached)
{
object entityCurrentlyInDB = null;
if (context.TryGetObjectByKey(entityWithChanges.EntityKey, out entityCurrentlyInDB))
{
context.ApplyPropertyChanges(entityWithChanges.EntityKey.EntitySetName, entityWithChanges);
foreach (var relatedEnd in ((IEntityWithRelationships)entityCurrentlyInDB).RelationshipManager.GetAllRelatedEnds())
{
var oldRef = relatedEnd as EntityReference;
if (oldRef != null)
{
var newRef =
((IEntityWithRelationships)entityWithChanges).RelationshipManager
.GetRelatedEnd(oldRef.RelationshipName, oldRef.TargetRoleName) as EntityReference;
oldRef.EntityKey = newRef.EntityKey;
}
}
}
else
{
throw new ObjectNotFoundException();
}
}
}
This is just a modified version of what I found
Here
Appreciate the help.
UPDATE:
This is the Update Method
public static void UpdateTemplate(Template template)
{
using (TheEntities context = new TheEntities())
{
context.ApplyChanges(template);
try
{
context.SaveChanges();
}
catch (OptimisticConcurrencyException)
{
context.Refresh(RefreshMode.ClientWins, template);
context.SaveChanges();
}
context.RemoveTracking(template);
}
}
This is the unit test:
[TestMethod]
public void CanUpdateATemplate()
{
Template template = new Template();
template.Name = "Test";
template.Description = "Test";
TemplateType type = TemplateManager.FindTemplateTypeByName("Test");
if (type == null)
{
type = new TemplateType();
type.Name = "Test";
}
template.TemplateType = type;
TemplateManager.AddTemplate(template);
template = TemplateManager.FindTemplateByID(template.TemplateID);
Assert.IsNotNull(template);
type = TemplateManager.FindTemplateTypeByName("Round");
if (type == null)
{
type = new TemplateType();
type.Name = "Round";
}
template.TemplateType = type;
TemplateManager.UpdateTemplate(template);
template = TemplateManager.FindTemplateByID(template.TemplateID);
Assert.IsNotNull(template);
Assert.IsTrue(template.TemplateType.Name == "Round");
TemplateManager.DeleteTemplate(template);
template = TemplateManager.FindTemplateByID(template.TemplateID);
Assert.IsNull(template);
}
This is simply not possible due to the way Detach works in EF.
I found that if I added key information myself I could get the generic call to work and even save it.
The problem is that the moment you go to return an entity after calling Detach on it you lose all relationship data. Ive found some write ups on writing graph managers for each entity but I find that a waste seeing as EF should do this stuff (supposedly it will in v2).
EF simply is not ready for N-Tier deployments.