MongoDB용 WCF Data Services Provider 구현 시도
23839 단어 Provider
WCF Data Services에 대한 설명은 다음과 같습니다http://www.cnblogs.com/shanyou/archive/2010/02/14/1668210.html.
데이터 노출 서비스로서 백엔드의 각종 데이터 원본의 전시를 지원할 수 있다. WCF 데이터 서비스는 기본적으로 실체 프레임워크(Entity Framework)를 지원하고 자신의 Provider를 실현할 수 있도록 확장 인터페이스를 제공한다.
먼저 Provider를 직접 구현해야 하는지 확인해야 합니다.
대부분의 경우 Reflection Provider는 이미 충분하다. 예를 들어 대상 데이터베이스(dbo4), 현재 핫한 NosQL, 즉 Document(-based) DataBase도 쉽게 실현할 수 있다.
http://www.cnblogs.com/tansm/archive/2010/06/10/1755250.html의 번역문을 읽으면 자동적으로Provider를 사용자 정의할 수 있습니다.
최근 며칠 동안 MongoDB의 WCF Data Services Provider를 실현해 봤습니다.
먼저, MongoDB의 NoRM 드라이브를 시도했습니다. 소개: http://www.cnblogs.com/shanyou/archive/2010/06/04/1751734.html
하지만 이 드라이버로 인해 ObjectId 를 솔리드 객체에 명시적으로 추가해야 합니다.id의 속성을 저장할 수 있습니다. 즉 콜렉션을 쉽게 호출할 수 있습니다.Save 메서드,이 속성이 없으면 Update 방법을 통해서만 데이터를 업데이트할 수 있지만 Update 방법은 Data 서비스에서 엉뚱한 문제에 부딪히기 때문에 여러 가지 기교를 시도한 후에 이 드라이브를 포기합니다.
그리고 사용mongodb-csharp driver을 바꾸면 이 구동도 완벽하지 않은 부분이 많다. 특히 LINQ에 대한 지원은 NoRM이 좋지 않았지만 최종적으로 몇 차례의 회전을 거쳐 기본 기능을 실현했다.이 드라이버를 사용하여Provider를 실현하는 가장 간단한 방법은 바로 이 글에서 말한 방법입니다. http://blog.dynamicprogrammer.com/2009/11/10/UsingMongoDBFromC.aspx 실체 클래스에 Document InternalDocument {get; set;},그러나 이렇게 하면 실체류에 대해 매우 큰 침입성을 가진다.나는 이런 방식을 채택하지 않았다.나의 최종 실현 방법은 실체류에 대한 영향을 최소화할 수 있다.
예를 들면 다음과 같습니다.
public class Team
{
public int ID { get; set; }// Document Id
public string Name { get; set; }
public string Odds { get; set; }
}
public class Group
{
[MongoId]
public string Name { get; set; }// Document Id
public List<Team> Teams { get; set; }
}
전체Provider는 IUpdatable 인터페이스를 실현한 클래스로 이 클래스는 정적 방법으로 대응하는 데이터베이스를 얻을 수 있다. 예를 들어 다음과 같다.public class MongoDBDataContext : IUpdatable
{
private static IMongoDatabase _db;
public IMongoDatabase DB
{
get
{
if (_db == null)
{
Mongo mongo = new Mongo();
mongo.Connect();
_db = mongo.GetDatabase(this.DataBaseName);
}
return _db;
}
}
public virtual string DataBaseName
{
get { return "temp"; }
}
}
이 Provider를 실현하려면 이 MongoDBDataContext를 계승하고 DataBaseName 속성을 다시 써서 자신의 데이터베이스 이름을 설정하고 DataServices를 설치하는 규범에 IQueryable의 속성을 추가하십시오. 예를 들어:public class WorldCupData : MongoDBDataContext
{
public override string DataBaseName
{
get
{
return "WorldCup";
}
}
public IQueryable<Team> Teams
{
get
{
return DB.GetCollection<Team>("Team").Linq();
}
}
public IQueryable<Group> Groups
{
get
{
return DB.GetCollection<Group>("Group").Linq();
}
}
}
구현 과정에서 가장 어려운 것은 Document를 정확하게 가져오고 저장하는 것입니다.반사를 통해 Document와 Entity를 동적으로 변환하고 Entity의 ID(또는 MongoId로 표시)의 속성의 ToString을 Document의 로 설정하는 절충안을 취했습니다.id,id도 항상 문자열입니다.핵심 코드는 다음과 같습니다.private static BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.SetProperty;
private static Document GetDocumentFromEntity(object entity,Type entityType)
{
if (entity == null) return null;
Document doc = new Document();
var properties = entityType.GetProperties(flags);
foreach (var pro in properties)
{
object proGetValue = pro.GetValue(entity, null);
if (pro.Name.ToLower() == "id" || pro.Name.ToLower() == "_id")// Document Id
doc.Id = proGetValue.ToString();
else if (Attribute.IsDefined(pro, typeof(MongoIdAttribute)))// Document Id
doc.Id = proGetValue.ToString();
doc[pro.Name] = proGetValue;
}
return doc;
}
private static object GetEntityFromDocument(Document doc, string fullTypeName)
{
if (doc == null) return null;
Type t = Type.GetType(fullTypeName, true);
object entity = Activator.CreateInstance(t);
var properties = t.GetProperties(flags);
foreach (var pro in properties)
{
if (doc.ContainsKey(pro.Name))
pro.SetValue(entity, doc[pro.Name], null);
}
return entity;
}
public object GetResource(IQueryable query, string fullTypeName)
{
object resource = null;
//query , ,
//foreach (var item in query)
//{
// resource = item;
//}
var exp = query.Expression as MethodCallExpression;
var arg1 = exp.Arguments[1] as UnaryExpression;
var expStr = arg1.Operand.ToString();//element => (element.ID == 0)
string[] fullTypeNameSplit = fullTypeName.Split('.');
var col= DB.GetCollection(fullTypeNameSplit[fullTypeNameSplit.Length - 1]);
//like to translate (element.ID == 0) to { ID : 0 }
string expStrSplit1 = expStr.Split('>')[1].Trim();//(element.ID == 0)
var valueStr = expStrSplit1.Split(new string[] { "==" }, StringSplitOptions.RemoveEmptyEntries)[1].Trim();//0)
valueStr = valueStr.TrimEnd(')');
var selector = new Document { Id = valueStr };
var doc = col.FindOne(selector);
resource = GetEntityFromDocument(doc, fullTypeName);
// fullTypeName can be null for deletes
if (resource != null && fullTypeName != null && resource.GetType().FullName != fullTypeName)
throw new Exception("Unexpected type for resource");
return resource;
}
GetResource 방법에서 안전하지 않은 작은 기교를 사용했음을 주의하십시오.이 구동의 LINQ가 완벽하지 않아서query가 작동하지 않기 때문에 표현식을 가져와 조건값을 해석할 수 밖에 없습니다.더욱이 앞의 약속에 의하면 이 조건값은 Document의 이다id. 전체 Provider의 원본 코드와 테스트 클라이언트는 http://code.msdn.microsoft.com/DSPforNoSQL에서 다운로드할 수 있습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Android 기본 요약: (11) ContentResolver 와 ContentProvider 가 어떻게 연결 되 었 는 지응용 프로그램 은 하나의 완전한 응용 프로그램 입 니 다. 예 를 들 어 특정한 apk 는 하나의 응용 프로그램 에 대응 합 니 다. 그 안에 n 개의 Activity 가 포 함 될 수 있 습 니 다. 관련 류...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.