Query Membership using Linq - asp.net-mvc

I am not a experienced programmer, I need to query the Membership User Collection provided in asp.net mvc.
I want the members be able to add other members as friends, I have created a added friend table.
Id,
MemberId,
Friend_MemberId,
DateAdded
I want to display a list of Members which are not added to this list (like filter already existing friends), but unable to query using linq, can anyone suggest a way, links, articles, would it be better to extend memebership class.

There are quite a number of ways you could go about this.
Let's examine one.
You can download the working VS2008 solution here. The example is not an MVC project, but the membership provider works the same regardless.
Stipulations:
You are using default default SqlProviders
You know how to add an ADO.Net Entity Model using the ASPNETDB
Your ASPNETDB serves one application, the default '/'. If this is not the case then you will already have the necessary knowledge to adjust the following guidance.
Create the Friends table in the ASPNETDB:
The following assumes that you are using the default ASPNETDB that is created in app_data. If not, then you have already created and connected to another DB, just take what you need.
Select your project in Solution Explorer, click 'show all files' icon at the top of Solution Explorer, expand 'App_Data' folder and right-click>Open ASPNETDB.MDF.
In Server Explorer you will see your ASPNETDB.
Project>Add New Item>Text File>Friends.sql
Paste query below. Save.
Right click in editor>Connection>Connect>select ASPNETDB
Right click in editor>Execute SQL
Friends.sql
/* To prevent any potential data loss issues, you should review this script in detail before running it outside the context of the database designer.*/
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE dbo.Friends
(
Id int NOT NULL IDENTITY (1, 1),
MemberId uniqueidentifier NOT NULL,
Friend_MemberId uniqueidentifier NOT NULL,
DateAdded datetime NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Table1 ADD CONSTRAINT
DF_Table1_DateAdded DEFAULT GetDate() FOR DateAdded
GO
ALTER TABLE dbo.Table1 ADD CONSTRAINT
PK_Table1 PRIMARY KEY CLUSTERED
(
Id
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ALTER TABLE dbo.Table1 ADD CONSTRAINT
IX_Table1 UNIQUE NONCLUSTERED
(
MemberId,
Friend_MemberId
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ALTER TABLE dbo.Table1 SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
Add an ADO.Net Entity Data Model to your project and include, at the minimum, the following:
Tables
Friends
Views
vw_aspnet_MembershipUsers
Query Example:
NOTE: I am by no means a Linq guru. These queries work fine and the generated sql does not seem unreasonable to me, but I am sure there is someone who will have helpful suggestions regarding possible optimizations of the queries.
// there are 3 users: User1, User2 and User3
// User1 has one friend, User2
string username = "User1"; // this would be the User.Identity.Name (currently logged in user)
//
vw_aspnet_MembershipUsers[] friends;
vw_aspnet_MembershipUsers[] notFriends;
using (var ctx = new ASPNETDBEntities())
{
// get the userId
Guid userId = ctx.vw_aspnet_MembershipUsers.First(m => m.UserName == username).UserId;
var usersFriendsQuery = from friend in ctx.Friends
join muser in ctx.vw_aspnet_MembershipUsers on friend.Friend_MemberId equals muser.UserId
where friend.MemberId == userId
select muser;
friends = usersFriendsQuery.ToArray();
Debug.Assert(friends.Count()==1);
Debug.Assert(friends[0].UserName=="User2");
var usersNotFriendsQuery = from muser in ctx.vw_aspnet_MembershipUsers
where ctx.vw_aspnet_MembershipUsers.Any(m =>
ctx.Friends.FirstOrDefault(friend =>
// include self in excluded members
(muser.UserId == userId)
||
// include already friends in excluded members
(friend.MemberId == userId && friend.Friend_MemberId == muser.UserId)
) == null)
select muser;
notFriends = usersNotFriendsQuery.ToArray();
Debug.Assert(notFriends.Count() == 1);
Debug.Assert(notFriends[0].UserName == "User3");
}
// do something interesting with friends and notFriends here

Related

Masterdata Services udpValidateModel Procedure

i've got a few tables in MDS.
One table (clients) ist filled via SQL and the other one is a masterdata table (country) filled by hand.
I have a business rule on table clients:
"Name must be unique" and no b-rule on Country.
I want to validate the data PROGRAMMATICALLY i do not want to CLICK "apply business rules" in explorer window on the webinterface.
I found several threads about how to use the sp mentioned in the title (udpValidateModel) to validate all entities in a model.
well...this thing does nothing. I can see the validationStatus in each of my tables "Awaiting Revalidation" after changing business rules or update data via sql. It doesnt matter what i do the status wont change (neither the validation icons in webui).
i also tried validateentity but the same "nothing" happens.
The SP below:
DECLARE #User_ID int
DECLARE #Model_ID int
DECLARE #Version_ID int
SET #User_ID = (SELECT ID FROM [MasterDataServices].[mdm].[tblUser] where userName = SYSTEM_USER )
SET #Model_ID = (SELECT Top 1 Model_Id FROM [MasterDataServices].[mdm].[viw_SYSTEM_SCHEMA_VERSION]
WHERE Model_MUID = 'MYMODELID')
SET #Version_ID = (SELECT Top 1 VersionNbr FROM [MasterDataServices].[mdm].[viw_SYSTEM_SCHEMA_VERSION]
WHERE Model_MUID = 'MYMODELID'
ORDER BY ID DESC )
EXECUTE [MasterDataServices].[mdm].[udpValidateModel] #User_ID, #Model_ID, #Version_ID, 1
Can anyone help?
SP 'udpValidateModel' works perfectly fine, looks like the parameters you are populating is not correct.
You may correct this as below and try; make sure that the system user has full authorization for the model.
SET #User_ID = (SELECT ID FROM [MasterDataServices].[mdm].[tblUser] where userName = SYSTEM_USER )
SET #Model_ID = (SELECT Top 1 Model_Id FROM [MasterDataServices].[mdm].[viw_SYSTEM_SCHEMA_VERSION]
WHERE Model_MUID = 'MYMODELID')
SET #Version_ID = (SELECT Top 1 VersionNbr FROM [MasterDataServices].[mdm].[viw_SYSTEM_SCHEMA_VERSION]
WHERE Model_MUID = #Model_ID
ORDER BY ID DESC )

Access the Kanban Column (a Team-Specific Field) for a Work Item

Is there a way to programmatically access the "Kanban Column" for a WorkItem using the TFS 2012 API?
Using the Scrum 2.2 template, the history of a Bug or Product Backlog Item shows "[MyProject\MyTeam] Kanban Column" as a changed field whenever a work item is dragged between Kanban columns on the Board, but the field is not accessible when specifically retrieving a work item through the TFS API.
It also shows up as a changed field in the WorkItemChangedEvent object when implementing the ProcessEvent method on the Microsoft.TeamFoundation.Framework.Server.ISubscriber interface.
Workaround:
A coworker found a blogpost about creating a read-only custom field to persist the value of the Kanban Column, taking advantage of the WorkItemChangedEvent to capture the latest value. It is then possible to query on this column. One problem with this approach is that only a single team's Kanban Column can be tracked.
Update:
According to this blogpost, the Kanban Column is not a field, rather a "WIT Extension". This may help lead to an answer.
I've found a way to read the value using the TFS 2013 API, inside the ISubscriber.ProcessEvent method:
var workItemId = 12345;
var extService = new WorkItemTypeExtensionService();
var workItemService = new WorkItemService();
var wit = workItemService.GetWorkItem(requestContext, workItemId);
foreach (var wef in extService.GetExtensions(requestContext, wit.WorkItemTypeExtensionIds))
{
foreach (var field in wef.Fields)
{
if (field.LocalName == "Kanban Column" || field.LocalName == "Backlog items Column")
{
// Access the new column name
var columnName = wit.LatestData[field.Field.FieldId];
}
}
}
If you are prepared to dig into the database you can mine this information out. I don't fully understand the modelling of the teams in TFS yet but first you need to work out which field id the team of interest is storing the Kanban state in as follows (TFS 2012):
USE Tfs_DefaultCollection
SELECT TOP(10)
MarkerField + 1 as FieldId,*
FROM tbl_WorkItemTypeExtensions with(nolock)
JOIN tbl_projects on tbl_WorkItemTypeExtensions.ProjectId = tbl_projects.project_id
WHERE tbl_projects.project_name LIKE '%ProjectName%
Then replace XXXXXXXX below with the FieldId discovered above
SELECT TOP 1000
wid.Id,
wia.State,
wid.StringValue as Kanban,
wia.[Work Item Type],
wia.Title,
tn.Name as Iteration
FROM tbl_WorkItemData wid with(nolock)
JOIN WorkItemsAre wia on wia.ID = wid.Id
JOIN TreeNodes tn on wia.IterationID = tn.ID
WHERE FieldId = XXXXXXXX and RevisedDate = '9999-01-01 00:00:00.000'
ORDER BY Id
I am not familiar with the Scrum 2.2 template, but the works are the same for CMMI or Scrum templates when it comes to TFS Work Item tracking.
Try something like this:
public string GetKanbanColumn(WorkItem wi)
{
if (wi != null)
{
return wi["Kanban"].ToString();
}
return string.Empty;
}
Depending on the actual name of the column, specified in the Work Item Template XML file. Hope this helps.

The member with identity ' ' does not exist in the metadata collection.\r\nParameter name: identity

I simplified the code a little while trying to debug:
[HttpPost]
public ActionResult Register(User model)
{
DateTime bla = new DateTime(2012, 12, 12);
try
{
User user = new User
{
gid = 1,
cid = 1,
firstName = model.firstName,
lastName = model.lastName,
email = model.email,
username = model.username,
password = model.password,
creationDate = bla,
active = 1
};
myContext.Users.AddObject(user);
myContext.SaveChanges();
}
catch (Exception ex)
{
throw ex;
}
return View();
}
The values are transmited accordingly. Users table:
[id] [int] IDENTITY(1,1) NOT NULL,
[cid] [int] NULL,
[gid] [int] NULL,
[firstName] [nvarchar](100) NOT NULL,
[lastName] [nvarchar](100) NOT NULL,
[email] [nvarchar](max) NOT NULL,
[username] [nvarchar](100) NOT NULL,
[password] [nvarchar](100) NOT NULL,
[creationDate] [datetime] NOT NULL,
[active] [int] NOT NULL,
CONSTRAINT [PK_Users_3213E83F0AD2A005] PRIMARY KEY CLUSTERED
I deleted all the foreign keys to be sure that nothing affects it. I am qute certain that at a previous moment it was working, but now I can not figure where the issue is.
It crashes while performing the savechanges:
{"An error occurred while updating the entries. See the inner exception for details."}
{"The member with identity '' does not exist in the metadata collection.\r\nParameter name: identity"}
I had the same error being thrown when I try to insert using EF, the error was
The member with identity 'Id' does not exist in the metadata collection.\r\nParameter name: identity
It wasn't obvious at first but the exception message was very concise because my database knows the column Id int but the property created for the object on my code was int ID so coming back to named mapping, Id is not mapped to ID.
So when an object with property ID is sent to database that only know Id you will get the above error.
I hope this helps, thanks
The issue was reproducing because of a trigger that was on the users table. Removed it and the issue is not reproducing anymore.
There is probably a trigger on the table being updated and it returns output. The output is thrown away but it conflicts with EF. Such output is often used to debug triggers (and forgotten to delete later):
select 'trigger called, i am here'
or there can be missing variable:
select column
instead of
select #variable=column
I think that the best solution is in this post. I used the 3rd option and works.
Here I report the reply in the link:
The issue could be related to a "instead of insert" trigger on one of
your tables.
The EF framework is performing validation on the inserted row of data
by calling scope_identity(). However, an "instead of insert" trigger
will change the context of the insertion in such a way that the EF
system's call to scope_identity will return null.
A couple ways around this:
Use a stored procedure to insert the data ( not tested )
Remove the instead of insert trigger ( triggers can cause other problems, so some people argue not to use them) ( tested, works!)
Turn off validation in the EF framework, so: context.Configuration.ValidateOnSaveEnabled = false ( tested, works!)
I had this same error today and spent a few frustrating hours trying to figure it out.
I was using Entity Framework to insert a record with an identity column into a SQL server database table. Simple enough.
The table had a trigger on it which in turn ran a stored procedure. The stored procedure had a line in it:
select newid()
This is the line that broke Entity Framework.
For tables with identity columns, Entity Framework expects to be returned a single row with a single field that is the identity column.
it's because of trigger pass back value to EF
if you are using trigger. in my problem i must check a value by selecting from other table and using of 'select' cause error in EF, so you must replace 'select' with 'set'.
you can not use this code.
select #any= any from tablename
you should use set instead of select
set #any= (select any from tablename)
Somedays, I hate M$.
The member with identity 'ChangeID' does not exist in the metadata collection.
Parameter name: identity
I've spent two days trying to get around this.
I'm using MVC.
To get all the data I need in one fell swoop, I created a view of the table in the DB for this application, and tables in other databases. (You may update views, with some constraints.)
I do a get, and all my data is present in the record, keys, descriptions, foreign keys, etc.
I created triggers on my view, to update the portion of the view that came from the local table.
Instead of Delete worked fine.
Instead of Update worked fine.
This error kept raising it's head on Instead of Insert. I could NOT get the insert trigger to successfully insert into my table. If I ran an insert on the view, with all fields provided in the SQL Management Studio, it worked fine. I know the exact values being passed because I ran SQL Server Profiler to see the code being passed.
But when the app attempted the update, it failed with The member with identity 'ChangeID' does not exist in the metadata collection.
Clue up above, someone said, "MVC expects table key to be ID"
I renamed ChangeID as ID in my view, changed it in the App, and BAM! Now it works.
What did NOT work:
db.Configuration.ValidateOnSaveEnabled = false;
adding a select to the trigger to get scope identity
Why do I have to modify my DB or my view to satisfy some hidden M$ assumption?
None the less, after two very frustrating days, code is now working. Maybe this will save someone else some time as well.
Try this
[HttpPost]
public ActionResult Register(User model)
{
DateTime bla = new DateTime(2012, 12, 12);
try
{
model.gid = 1;
model.cid = 1;
model.creationDate = bla;
model.active = 1;
myContext.Users.AddObject(model);
myContext.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
return View();
}
I was having this issue and my fix, was that in my connection-string metadata I did not specify my model in the .msl format.
See more info here
In my case, SetName of the entity was incorrect. Shortly, this worked for me:
Use
myContext.AddObject(nameOfSetEntity, user);
Instead of:
myContext.Users.AddObject(user);
To get the whole correct name of the entity (thanks to Nix's answer)
string className = typeof(User).Name;
var container = myContext.MetadataWorkspace.GetEntityContainer(myContext.DefaultContainerName, System.Data.Metadata.Edm.DataSpace.CSpace);
string nameOfSetEntity= (from meta in container.BaseEntitySets
where meta.ElementType.Name == className
select meta.Name).First();
Context.AddObject(nameOfSetEntity, user);

task and subtask in TFS

I'd like to know which is parent/child relationship for task in th TFS datawarehouse or db.
For example the parentID=15662 and childID=15667, where I can find this information in the DW or db?
I think this will get you close to what you need. It just pulls the parent UserStory with a particular ID and all of it's children. The work item types may need to be changed based on your team project template. You can look at the different link types in DimWorkItemLinkType and adjust the query accordingly to get the desired result.
USE Tfs_Warehouse
GO
SELECT story.System_ID AS StoryID
, story.System_Title AS StoryTitle
, task.System_ID AS TaskID
, task.System_Title AS TaskTitle
, linkType.ReferenceName
, linkType.LinkName
FROM CurrentWorkItemView story
LEFT JOIN dbo.vFactLinkedCurrentWorkItem linkToStory
ON story.WorkItemSK = linkToStory.SourceWorkItemSK
LEFT JOIN CurrentWorkItemView task
ON linkToStory.TargetWorkitemSK = task.WorkItemSK
AND task.System_WorkItemType = 'Task'
LEFT JOIN dbo.DimWorkItemLinkType linkType
ON linkToStory.WorkItemLinkTypeSK = linkType.WorkItemLinkTypeSK
WHERE story.System_WorkItemType = 'User Story'
AND story.System_ID = 15662

How To Save Navigation Properties in the Entity Framework

I'm trying to use the repository pattern to save an entity using the Entity Framework. I'm unclear on how to save the Navigation Properties (like Account below). Can anyone shed some light on this. Especially how one would set the AccountId from an MVC controller all the way through to the repository where it's saved.
Thanks!
--- Sample Code ---
public void SavePerson(Person person)
{
if (person != null)
{
using (xxxxxxEntities bbEntities = new xxxxxxEntities())
{
//see if it's in the db
Person cPerson;
ObjectQuery<Person> persons = bbEntities.Person;
cPerson = (from p in persons
where p.PersonId == person.PersonId
select p).FirstOrDefault() ?? new Person();
//synch it
cPerson.Account.AccountId = person.Account.AccountId; //<=== ????
cPerson.Active = person.Active;
cPerson.BirthDay = person.BirthDay;
cPerson.BirthMonth = person.BirthMonth;
cPerson.BirthYear = person.BirthYear;
cPerson.CellPhone = person.CellPhone;
cPerson.CreatedBy = person.CreatedBy;
cPerson.CScore = person.CScore;
Etc....
I think you may be going about this the hard way. There are lots of posts on the repository pattern, the way that works best with MVC is to get the item, then update it with the form, then save it. What you're doing is passing the item through to your repository, getting it again and then updating it with the object.
But that's not the problem you asked about;
cPerson.Account = (from a in Account
where a.AccountId.Equals(person.Account.AccountId)
select a).FirstOrDefault();
You need to set the Account object to an instance of the account you're trying to reference like this. You could, and probably should, extract this code into a seperate repository for the account, just make sure they share the same Entity context.

Resources