2014-11-10 1 views
2

이 작업을 수행 할 수 있는지 여부는 확실하지 않지만 가능한 경우 SQL 문자열을 사용하지 않으려합니다. 내가 쉽게 TABLENAME 및 formId 동적으로 주어지고 문제를 실행하지 않습니다 루프에이를 넣을 수 있습니다LINQ를 사용하여 동적으로 다른 테이블을 쿼리 할 수 ​​있습니까?

string sql = "UPDATE " + tableName + " SET Status=0 WHERE Id=" + formId.ToString(); 

: 내가 Linq에/DbContexts와 함께 할 싶은 것은 SQL을 쉽게 수행 할 수 있습니다 다음과 같다.

나는 여러 DbContexts, 그래서 내가 좋아하는 뭔가를 할 수있는 방법을 알고하지 않습니다 도움을

var db = new *dynamicallyChosenContext*() 

var query = from p in db.*dynamicallyChosenAlso* 
      where p.Id == formId 
      select p; 

foreach (var result in query) 
{ 
    result.Status = 0; 
} 

db.SaveChanges() 

감사합니다!

+0

반사 ....? – gdoron

+0

그로스 (Gross) ... 나는 그렇게하기를 원하지 않는다. SQL로 매우 쉽기 때문에 이렇게하는 방법이 있어야한다고 생각했다. – Tevis

+0

모든 EF 엔티티에는'Id'와'Status' 속성이 있습니까? 문제는 LINQ 자체와 관련이 적습니다. C#은 정적으로 형식이 지정된 언어입니다. 일반에서 사용하려는 공통 속성을 나타내는 기본 형식을 사용하지 않고 (쉽게) 수행 할 수 없습니다. 질문. – rsenna

답변

0

함수 프로그래밍에서 Currying이라고하는 기술이 있습니다. 여기서는 원하는만큼 매개 변수를 전달하여 액세스 할 수 있습니다. 여기 예가 있습니다 : http://blogs.msdn.com/b/sriram/archive/2005/08/07/448722.aspx

P.S : 커링 기능을 사용하여 DBContexts를 반복 할 수 있습니다.

+0

감사합니다. – Tevis

0

'코드'를 사용하고 SQL 문자열을 사용하지 않으려면 리플렉션을 사용해야한다고 생각합니다. 즉 이것은 당신이 그것을 할 수있는 방법입니다 ... C#을 작동 단지 방법은 다음과 같습니다

using System; 
using System.Data.Entity; 
using System.Linq; 

public class TestContext : DbContext 
{ 
    public DbSet<Box> Boxes { get; set; } 
    public DbSet<Thing> Things { get; set; } 
} 

public abstract class Base 
{ 
    public int Id { get; set; } 
} 

public class Box : Base 
{ 
    public string Title { get; set; } 
} 

public class Thing : Base 
{ 
    public string Name { get; set; } 
} 

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     var db = new TestContext(); 

     DoIt(GetPropValue(db, "Boxes") as IQueryable<Base>); 
     DoIt(GetPropValue(db, "Things") as IQueryable<Base>); 
    } 

    private static void DoIt(IQueryable<Base> b) 
    { 
     Console.WriteLine(
      b.Single(t => t.Id == 1).Id); 
    } 

    private static object GetPropValue(object src, string propName) 
    { 
     return src.GetType().GetProperty(propName).GetValue(src, null); 
    } 
} 

은 확실히 당신은 당신이 필요로하는 어떤 목록 등의 문자열을 넣을 수 있습니다.

1

다음은 리플렉션을 사용하지 않고 다른 컨텍스트에서 런타임에 다른 테이블을 업데이트 할 수있는 작업 코드입니다.

namespace DemoContexts 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Data.Entity; 
    using System.Linq; 


    public interface IThing 
    { 
     int Id { get; set; } 
     int Status { get; set; } 
    } 

    public class FirstPersonThing : IThing 
    { 
     [System.ComponentModel.DataAnnotations.Key] 
     public int Id { get; set; } 
     public int Status { get; set; } 
     public string Foo { get; set; } 
    } 

    public class SecondPersonThing : IThing 
    { 
     [System.ComponentModel.DataAnnotations.Key] 
     public int Id { get; set; } 
     public int Status { get; set; } 
     public string Bar { get; set; } 
    } 

    public class FirstContext : DbContext 
    { 
     public FirstContext() : base("FirstContext") { } 
     public DbSet<FirstPersonThing> MyThings { get; set; } 
     public DbSet<SecondPersonThing> YourThings { get; set; } 
    } 

    public class SecondContext : DbContext 
    { 
     public SecondContext() : base("SecondContext") { } 
     public DbSet<FirstPersonThing> MyThings { get; set; } 
     public DbSet<SecondPersonThing> YourThings { get; set; } 
    } 


    class Program 
    { 
     static void Main(string[] args) 
     { 
      int contextType = 1; 
      int thingType = 1; 

      DbContext db = RunTimeCreatedContext(contextType); 
      IQueryable<IThing> collection = RunTimeCreatedCollection(db, thingType); 

      UpdateRuntimeDeterminedThings(db, collection, 1); 

      Console.ReadLine(); 
     } 

     public static void UpdateRuntimeDeterminedThings(DbContext db, 
               IQueryable<IThing> collection, 
               int formId) 
     { 
      var querySet = collection.Where(p => p.Id == formId).ToList(); 
      foreach (var result in querySet) 
      { 
       result.Status = 0; 
      } 

      db.SaveChanges(); 
     } 

     static DbContext RunTimeCreatedContext(int contextType) 
     { 
      if (contextType == 0) 
      { 
       return new FirstContext(); 
      } 
      else 
      { 
       return new SecondContext(); 
      } 
     } 

     static IQueryable<IThing> RunTimeCreatedCollection(DbContext db, int thingType) 
     { 
      if (thingType == 0) 
      { 
       return db.Set(typeof(FirstPersonThing)) as IQueryable<IThing>; 
      } 
      else 
      { 
       return db.Set<SecondPersonThing>(); 
      } 
     } 
    } 
} 

주의해야 할 첫 번째 일은이 모든 정적으로 이러한 개체는 공유 재산 서명이 있어야합니다 서로 다른 유형의 개체에 대한 일반적인 쿼리를 수행 할 수 있도록 입력되며,이 개념적으로 IThing 인터페이스로 표현된다는 점이다.

두 번째로 주목해야 할 점은 IQueryable이 어떻게 생성되는지입니다. 첫 번째 인스턴스 (FirstPersonThings의 경우)에서 DbContext.Set Method (Type)에 의해 생성되고 두 번째 인스턴스의 DbContext.Set<TEntity> Method에 의해 생성됩니다. 첫 번째는 런타임에 결정된 유형을 사용하고 캐스트가 필요하지만 런타임시 전달 유형을 사용하는 것이 유용 할 수 있으며 두 번째 유형은 generics를 사용하며 유형은 컴파일 타임에 결정됩니다. 분명히이 기능이 작동 할 수있는 여러 가지 다른 방법이 있습니다.

마지막으로 UpdateRuntimeDeterminedThings 메서드는 형식간에 공유되며 (기본 형식/상속 또는 인터페이스 구현과 함께) 속성과 메서드를 사용하기 때문에 작동합니다.

이것은 동적 프로그래밍 (동적 유형을 사용하여 가능함)이 아니며이 기능의 작동 방식을 설명하기 위해 동적이 아닌 런타임이라는 용어를 사용했습니다.

관련 문제